React 状态扩展多层对象无法正常工作

3

状态默认值

state = {
        moveType: {
            value: 0,
            open: false,
            completed: false
        }
    };

// 更新新状态的回调函数

let step = 'moveType';
let val = 3; // new value
let newObj = { ...this.state[step], value: val };
console.log(newObj);
this.setState({[step]: newObj }, function () {console.log(this.state);});

console.log(newObj) 显示了新值,但是 this.state 仍然显示旧值。你能告诉我我做错了什么吗?


根据文档,"setState() 并不总是立即更新组件。它可能会批量或延迟更新直到稍后。" (https://facebook.github.io/react/docs/react-component.html#setstate) - Anthony Kong
@AnthonyKong,根据文档,“setState()的第二个参数是一个可选的回调函数,它将在setState完成并且组件重新渲染后执行。”难道回调不应该包含新值吗? - elmeister
你的意思是 console.log(this.state); 记录了旧值?我很惊讶它居然记录了什么。在回调函数内部,this 不是 指向 React 组件。 - Felix Kling
@FelixKling,好的,将function()改为() =>或者使用self代替this - 效果是一样的。 - elmeister
Basil,React如何渲染组件是一个相当长的故事,但如果你将这段代码移出render函数的事件处理程序之一,事情就会奏效。 - elmeister
1个回答

2

在React中设置状态是一件非常敏感的事情。 我使用的最佳实践是始终手动控制对象的深度合并,并使用this.setState(state => { ... return new state; })这种类型的调用,就像这个例子中一样:

this.setState(state => ({
  ...state,
  [step]: { ...(state[step] || {}), ...newObj },
}), () => console.log(this.state));

片段更新开始

[步骤]: { ...state[步骤], ...newObj }

更改为:

[步骤]: { ...(state[步骤] || {}), ...newObj }

以正确处理状态尚未具有此步骤键的情况

片段更新结束

问题是,当您使用this.state(在let newObj = { ...this.state[step]中)时,它可能具有过时的值,因为您刚刚几毫秒前调用了一些待处理(尚未合并)的状态更改。

因此,我建议使用回调方法:this.setState(state => { ...使用状态并返回新状态;}),它保证您使用的state具有最新的值


结果与上面的代码示例仍然相同。是的,我有几个毫秒级的调用,一个接一个地更新同一个对象,我认为一旦它被更新一次,它就不会与其他内容合并了...因为它只会更新最后合并的值。 - Basit
你能提供更多的代码吗,展示一下你是如何进行这些毫秒调用的吗? - Jevgeni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接