自动更新React的上下文是通常的行为吗?

时间:2019-07-24 12:22:04

标签: reactjs

我认为上下文的作用与状态类似,因此我创建了函数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 */};

1 个答案:

答案 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