不同的 Child 组件通过同时调用 setState 弄乱了 parent 的状态
Different Child Components mess up State of parent by calling setState at the same time
我正在创建一个基于间隔的游戏。 parent 组件创建一个时间间隔并让其 children 注册每个时间间隔触发的回调。
我的设置看起来像
<ParentComponent>
<Child1 />
<Child2 />
...
</ParentComponent>
parent 使用 React.cloneElement
并为每个 child
提供一个方法
registerCallback( callback, id ) {
const { callbacks } = this.state;
this.setState({
callbacks: callbacks.concat({
callback,
id
})
})
}
这种方法效果很好。但是现在我有两个 children 从 componentDidMount()
.
中调用 registerCallback()
方法
现在只有 <Child2 />
将其回调存储在 parents 状态。
当我延迟 registerCallback()
方法的调用时
setTimeout(() => {
registerCallback(callbackFunction, id)
}, 50 )
它运行良好。但这感觉像是一个非常错误的 hack,特别是因为我需要 "guess" 状态需要更新多长时间。
所以我的结论是状态更新太慢了,而是在我的组件之外定义了一个数组并更新了它。奇怪的是,如果我改变这个数组,它就可以正常工作。
所以如果我使用
array.push({callback, id})
我的数组看起来像 [callback1, callback2]
但是因为我不想改变我的数组我试过了
array.concat({callback, id})
这给我留下了 []
虽然我的状态看起来像 [array2]
我怎样才能在 parent 中改进我的方法,让 children 可以随时随地毫无问题地调用 registerCallback()
。
正如您正确推断的那样,问题是 setState 是异步的,因此到第二个 child 调用 registerCallback 时,第一个 child 的状态更改尚未传播到 this.state.尝试:
registerCallback( callback, id ) {
this.setState(({ callbacks }) => ({
callbacks: callbacks.concat({
callback,
id
})
})
}
您将函数作为第一个参数传递给 setState。此函数接收当前状态(上面解构为 { callbacks }
)并且应该 return 新状态。该函数将立即被调用,或者在先前的状态更改传播时被调用,因此它的状态保证是新鲜的。因此,您避免使用可能过时的 this.state
.
这是一篇关于它的文章:
https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3
我正在创建一个基于间隔的游戏。 parent 组件创建一个时间间隔并让其 children 注册每个时间间隔触发的回调。
我的设置看起来像
<ParentComponent>
<Child1 />
<Child2 />
...
</ParentComponent>
parent 使用 React.cloneElement
并为每个 child
registerCallback( callback, id ) {
const { callbacks } = this.state;
this.setState({
callbacks: callbacks.concat({
callback,
id
})
})
}
这种方法效果很好。但是现在我有两个 children 从 componentDidMount()
.
registerCallback()
方法
现在只有 <Child2 />
将其回调存储在 parents 状态。
当我延迟 registerCallback()
方法的调用时
setTimeout(() => {
registerCallback(callbackFunction, id)
}, 50 )
它运行良好。但这感觉像是一个非常错误的 hack,特别是因为我需要 "guess" 状态需要更新多长时间。
所以我的结论是状态更新太慢了,而是在我的组件之外定义了一个数组并更新了它。奇怪的是,如果我改变这个数组,它就可以正常工作。
所以如果我使用
array.push({callback, id})
我的数组看起来像 [callback1, callback2]
但是因为我不想改变我的数组我试过了
array.concat({callback, id})
这给我留下了 []
虽然我的状态看起来像 [array2]
我怎样才能在 parent 中改进我的方法,让 children 可以随时随地毫无问题地调用 registerCallback()
。
正如您正确推断的那样,问题是 setState 是异步的,因此到第二个 child 调用 registerCallback 时,第一个 child 的状态更改尚未传播到 this.state.尝试:
registerCallback( callback, id ) {
this.setState(({ callbacks }) => ({
callbacks: callbacks.concat({
callback,
id
})
})
}
您将函数作为第一个参数传递给 setState。此函数接收当前状态(上面解构为 { callbacks }
)并且应该 return 新状态。该函数将立即被调用,或者在先前的状态更改传播时被调用,因此它的状态保证是新鲜的。因此,您避免使用可能过时的 this.state
.
这是一篇关于它的文章:
https://medium.com/@wereHamster/beware-react-setstate-is-asynchronous-ce87ef1a9cf3