我认为上下文的作用与状态类似,因此我创建了函数handleUpdate
,该函数可以更新state
,它是上下文用作值。之后,我注意到上下文是在不触发handleUpdate
的情况下进行更新的。
提供者:
<DashboardContext.Provider value={{dashboard:this.state,handleChange:this.handleChange}}>
{/*...*/}
</DashboardContext.Provider>
handleChange函数
handleChange=(what, value)=> this.setState({[what]:value});
在另一个使用上下文的组件中:触发上下文更新,无需调用handleUpdate
。
let updatedTasks = this.context.dashboard.tasks;
updatedTasks[task.id] = {/* ... something */};
然后,它更改上下文值和父状态(使用上下文),而无需调用setState
。这是通常的行为吗?我虽然应该使用setState
函数来处理所有状态。
作为我丢失了对上下文对象的引用的实际解决方法,
let updatedTasks = JSON.parse(JSON.stringify(this.context.dashboard.tasks));
但这对我来说似乎不是正确的解决方案。
编辑:作为@尼古拉斯大厦建议的解决方案: 我当前的代码
构造函数中的状态现在看起来像这样:
this.state = {
value: {
dashboard: {
// everything from state is now here
},
handleChange: this.handleChange,
}
};
我现在传递state.value而不是自定义对象
<DashboardContext.Provider value={this.state.value}>
{/*...*/}
</DashboardContext.Provider>
但是仍然在执行此操作时,上下文和状态(两者)都在不调用handleChange的情况下被更新
let updatedTasks = this.context.dashboard.tasks;
updatedTasks[task.id] = {/* ... something */};
答案 0 :(得分:1)
您遇到的问题位于此部分:
value={{dashboard:this.state,handleChange:this.handleChange}}
每次(无论出于何种原因)渲染组件时,此行都会创建一个新对象。仪表板属性和handleChange属性可以保持不变,但它们周围的对象始终是新的。这就足够了,每次渲染时,值都会改变,因此使用该值的所有后代也需要重新渲染。
您将需要修改代码,以使该对象引用不会更改,除非您希望更改。这通常是通过将对象置于组件状态来完成的。
class Example {
handleChange = (what, value) => {
this.setState(oldState => ({
value: {
... oldState.value,
[what]:value
}
});
}
state = {
value: {
dashboard: {
// whatever you used to put in state now goes here
},
handleChange: this.handleChange
}
}
render() {
return (
<DashboardContext.Provider value={this.state.value}>
{/*...*/}
</DashboardContext.Provider>
)
}
}
您可以在React的上下文文档中看到对此的提及:https://reactjs.org/docs/context.html#caveats