javascript - react 上下文重新渲染提供者的每个 child ?

标签 javascript reactjs react-component react-context

    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

数字和文本的背景颜色都会发生变化。

React 上下文应该只为提供者重新渲染消费者,对吧?为什么它要重新渲染 Provider 的所有子级?

我预计,一旦单击“更改数字”按钮,只有数字更改会保持数字和文本的背景颜色相同,并低于控制台的输出,因为只有消费者才应该重新渲染而不是文本和数字组件。

rendering app

我错过了什么?

我从 sandbox 获取了代码

最佳答案

当您更新 App 组件中的状态时,

WrappedNumberWrappedText 会重新渲染,因为在 Virtual DOM 中,它们与 Provider 位于同一层次结构中,并且当父组件组件更新子组件也会更新。

为了避免它们重新渲染,您可以将它们作为应用程序的子项提供,例如

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
);

关于javascript - react 上下文重新渲染提供者的每个 child ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61599315/

相关文章:

javascript - 如何使用 fetch.response.json() 的 reviver 函数

javascript - 为什么我会收到此 JS 错误?

javascript - 异常在 promise 链中被吞没

reactjs - 使用Redux在组件之间共享登录状态

reactjs - React.js 建议直接将 `props` 分配给状态

javascript - 比使用大量 else if 语句更有效的方法

javascript - 循环数组并填充矩阵 - JS

javascript - {Link} 在 reactjs 中没有获取正确的 URL

javascript - react 警告 : Functions are not valid as a React child

javascript - 如何将混合内容解析为React组件?