我有一个组件可以在其中创建新帖子。我有一个状态,用于配置和创建表单。该状态下的主要对象称为formControls
,每个元素内部的外观如下:
title: {
elementType: "input",
elementConfig: {
type: "text",
placeholder: "Title"
},
value: "",
validation: {
required: true
},
valid: false,
isTouched: false
}
然后我有一个提交处理程序,在其中创建新帖子,然后尝试清除输入。我正在使用2种方式进行绑定,因此我尝试通过遍历状态来进行清除,进行复制并更新formControls
:title, author and content
中每个元素的值,如下所示:
for (let key in this.state.formControls) {
const updatedState = { ...this.state.formControls };
const updatedInput = { ...this.state.formControls[key] };
updatedInput.value = "";
updatedState[key] = updatedInput;
console.log(updatedState);
this.setState({
formControls: updatedState
});
}
问题在于,它仅清除形式(文本区域)中的最后一个元素。我在控制台上登录了updatedState
,并在每次迭代中清除当前输入,但在下一次迭代中,先前清除的输入在清除之前再次具有该值,因此最后只清除了最后一个元素。如果我移动const updatedState = { ...this.state.formControls };
在for循环之外的行为是应有的。这是由于setState()
的异步操作而发生的,并且在我尝试在每次迭代中进行更新时都没有给我正确的先前状态吗?
我希望也许有人可以帮助我理解为什么会这样。我会发布更多代码,但时间很长。
答案 0 :(得分:1)
在第一次调用setState
之后,关闭中可用的数据已过时。 for .. in
块中的所有迭代都将使用“旧”数据运行,因此您的最后一次迭代实际上是将字段设置为for .. in
循环开始时的值。 / p>
尝试仅调用一次setState
,然后将所有需要的更改都放入其中。
const updatedFormControls = { ...this.state.formControls };
for (let key in this.state.formControls) {
const updatedInput = { ...updatedFormControls[key] };
updatedInput.value = "";
updatedFormControls[key] = updatedInput;
}
console.log(updatedFormControls);
this.setState({
formControls: updatedFormControls
});
做同样事情的另一种方法可能看起来像这样:
this.setState(state => ({
...state,
formControls: Object.keys(state.formControls).reduce(
(acc, key) => ({
...acc,
[key]: { ...state.formControls[key], value: '' }
}),
{}
)
});