我有一个父组件,它有自己的状态,并且也在子组件之间共享。
在我的子组件中,我有一个表单,对于数据,我创建了一个本地状态。让我们调用这个子组件。
在我的父组件中,有一个按钮可以将数据从我的子组件的本地状态更新到我的父级状态。这是我通过从父母传递给孩子的标志来完成的。
另外,我的父母两次呈现相同的子程序,最后代码如下所示:
const parent = () => {
const [parentState, setParentState] = useState(null);
const [submitSignal, setSubmitSignal] = useState(false);
const handleSave = () => {
setSubmitSignal(true);
}
return (
<div>
<div onClick={handleSave}>
Save Data
</div>
<Child
pos={0}
key={0}
parentState={parentState}
submitSignal={submitSignal}
setParentState={setParentState}
/>
<Child
pos={1}
key={1}
parentState={parentState}
submitSignal={submitSignal}
setParentState={setParentState}
/>
</div>
)
}
const Child = (props) => {
const [childState, setChildState] = useState(null);
React.useEffect(() => {
const { pos, submitSignal, parentState, setParentState } = props;
if (submitSignal) {
setParentState(...parentState, ...childState);
}
}, [props.submitSignal])
return (
<div>
// A large form which multiple fields
</div>
)
}
现在发生的事情是,只要我使父组件中的submitSignal变为真,两个子组件同时接收它,并尝试更新父组件的状态。这是一种竞争条件,在此情况下,子0更新数据,但在父状态更新之前,Child 1还会更新父状态,从而覆盖/删除Child 0添加的内容。
请帮我解决这个问题。
P.S:,我之所以使用这个结构,是因为在我的孩子里,我有一个非常大的表单,相同的表单被使用了两次。
发布于 2021-07-26 14:02:53
您必须使用回调函数,而不是直接设置父状态。这样,您将在重写状态时得到更新的前一状态。
if (submitSignal) {
setParentState((pstate)=>{
return {...pstate,...childstate}
});
}
发布于 2021-07-27 10:02:49
我明白为什么你会困惑,这实际上是完全按照预期的工作。
在我继续之前:注意:
有关更多细节,请阅读我的文章如何反应-钩子-工作。它将帮助您更好地理解功能组件、生命周期和挂钩。
关于你的案子:
关于您的具体问题:遵循这代码沙箱,就像您的代码有一些日志一样。
订单
阶段顺序:
日志
这里没有任何赛车条件,如果1000个孩子请求更新(例如通过setstate ),那么react就不在乎了。因为所有更新请求都处于相同的阶段,因此将只调度一个呈现。
如果您很难理解它,我建议您阅读我的文章“如何反应-钩子-工作”,文章中有简单而复杂的示例来演示这些行为。
https://stackoverflow.com/questions/67798460
复制相似问题