使用 React 上下文将对象传递到 context.provider 的值时如何避免重新渲染

how to avoid re-rendering when passing the object into value of context.provider using React context

在 class 组件中,当我们想使用 react context 将对象传递给 context provider 的值时,我们有办法避免重新渲染问题。下面是代码

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      text: "",
      contextState: {
        count: 0,
        increment: this.increment
      }
    };
  }

  increment = () => {
    this.setState({
      contextState: {
        ...this.state.contextState,
        count: this.state.contextState.count + 1
      }
    });
  };

  onChange = e => {
    const { value, name } = e.target;
    this.setState({ [name]: value });
  };

  render() {
    return (
      <CountContext.Provider value={this.state.contextState}>
        <div style={styles}>
          <input name="text" value={this.state.text} onChange={this.onChange} />
          <div>Count: {this.state.contextState.count}</div>
          <Container1 />
          <Container2 />
        </div>
      </CountContext.Provider>
    );
  }
}

我们将 this.state.contextState 设为 CountContext.Provider 的值。因此,当用户在输入元素中键入任何内容时,不会导致 <Container1 /><Container2 /> 重新呈现。这是代码沙箱:https://codesandbox.io/s/qqx1jqk8mj?file=/src/index.js:260-1105

我想把它变成钩子。这是代码沙箱 https://codesandbox.io/s/affectionate-gauss-duk64?file=/src/index.js 但计数器无法正常工作。我可以知道哪一部分是错的吗?谢谢

在你的钩子组件中,你只需要使用函数式 setState 方法。

setContextState(prevState=>newState)

在您的代码中:https://codesandbox.io/s/admiring-shtern-g6oll?file=/src/index.js

  const [contextState, setContextState] = useState({
    count: 0,
    increment: () => {
      setContextState(prev=>({
        ...prev,
        count: prev.count + 1
      }));
    }
  });

你需要这样做的原因是状态值永远不会更新,因为它周围有闭包。 contextState.count 会一直保持为 0,因为它是状态最初设置时的值(0),不会改变。