使用 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
),不会改变。
在 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
),不会改变。