react context放弃了Provider的每个子对象?

问题描述 投票:0回答:1
    import React, { useReducer, useEffect ,Component} from "react";
    import ReactDOM from "react-dom";
    const AppContext = React.createContext();

import React from "react";

const withRandomColors = WrappedComponent => {
  return class RandomColors extends React.Component {
    constructor() {
      super();
      this.randomColors = [
        "red",
        "blue",
        "green",
        "cyan",
        "lavender",
        "skyblue",
        "orange",
        "pink",
        "yellow"
      ];
    }

    getRandomColors() {
      const num = Math.floor(Math.random() * 10) % 9;
      return this.randomColors[num];
    }

    render() {
       console.log("Rerendering wrapper Component");
      return <WrappedComponent randomColor={this.getRandomColors()} />;
    }
  };
};

class Number extends React.Component {
  constructor(props) {
    super(props);
  }

  componentDidMount() {}

  render() {
    console.log("rendering Number Component");
    return (
      <AppContext.Consumer>
        {({ number }) => {
          return (
            <div style={{ backgroundColor: `${this.props.randomColor}` }}>
              {number} <br />
            </div>
          );
        }}
      </AppContext.Consumer>
    );
  }
}

class Text extends React.Component {
  constructor(props) {
    super(props);
  }

  render() {
     console.log("rendering Text Component");
    return (
      <AppContext.Consumer>
        {({ text }) => (
          <div style={{ backgroundColor: `${this.props.randomColor}` }}>
            {text} <br />
          </div>
        )}
      </AppContext.Consumer>
    );
  }
}

const WrappedText=withRandomColors(Text);
const WrappedNumber=withRandomColors(Number);

class App extends Component {
  constructor() {
    super();
    this.state = {
      number: Math.random() * 100,
      text: "testing context api"
    };
  }

  updateNumber = () => {
    const randomNumber = Math.random() * 100;
    this.setState({ number: randomNumber });
  };

  render() {
    console.log("rendering app")
    return (
      <AppContext.Provider value={this.state}>
        <div>
          <h1>Welcome to React</h1>
          <WrappedNumber  />
          <WrappedText />
          <button onClick={this.updateNumber}>Change Number </button>
        </div>
      </AppContext.Provider>
    );
  }
}



ReactDOM.render(
  <App />,
  mountNode
);

当单击ChangeNumber按钮控制台时显示

rendering app

Rerendering wrapper Component

Rerendering Number Component

Rerendering wrapper Component

Rerendering Text Component

以及数字和文本的背景颜色都会改变。

反应上下文应该仅将提供者的消费者重新呈现,对吗?为什么要重新提供提供者的所有子代?

我希望只有数字更改才能使数字和文本的背景色保持相同,并且在单击更改数字按钮后从控制台输出以下,因为应该仅让使用者重新呈现文本和数字组件。

rendering app

我想念什么?

我从sandbox中获取了代码

javascript reactjs react-component react-context
1个回答
0
投票

WrappedNumberWrappedText会在您更新App组件中的状态时重新呈现,因为在虚拟DOM中它们与提供者位于同一层次结构中,并且当父组件更新时,子组件也会被更新。

为了避免它们重新呈现,您可以将它们作为App的子类提供

class App extends Component {
  constructor() {
    super();
    this.state = {
      number: Math.random() * 100,
      text: "testing context api"
    };
  }

  updateNumber = () => {
    const randomNumber = Math.random() * 100;
    this.setState({ number: randomNumber });
  };

  render() {
    console.log("rendering app")
    return (
      <AppContext.Provider value={this.state}>
        <div>
          <h1>Welcome to React</h1>
          {this.props.children}
          <button onClick={this.updateNumber}>Change Number </button>
        </div>
      </AppContext.Provider>
    );
  }
}

ReactDOM.render(
  <App >
      <WrappedNumber  />
      <WrappedText />
 </App>,
  mountNode
);
© www.soinside.com 2019 - 2024. All rights reserved.