我可以改变传递给 setState 函数的状态吗?

Posted

技术标签:

【中文标题】我可以改变传递给 setState 函数的状态吗?【英文标题】:Can I mutate state passed to setState function? 【发布时间】:2017-09-04 10:48:16 【问题描述】:

我知道我不应该直接在 React 中改变状态,但是当我使用函数时的情况如何:

onSocialClick = e => 
    const id = e.target.value;
    this.setState((prevState, props) => 
        prevState[id] = !(prevState[id]);
        return prevState;
    );
;

修改传递的对象会不会出错?

编辑:

事实证明,我们大多数人都错了。立即回复docs state it clearly:

state 是对应用更改时的组件状态的引用。它不应该直接突变。相反,应该通过基于 state 和 props 的输入构建一个新对象来表示更改

感谢@Tomáš Hübelbauer 在评论中指出这一点。

【问题讨论】:

这不是错误:) 不直接修改状态意味着你应该使用setState,而不是this.state =...。如果你这样做 - 一切都很好,无论你使用什么作为传入参数。 @Tomasz 我问了一个后续问题,因为我对您的代码 sn-p 有疑问。你可能会觉得这很有趣:***.com/q/47339643/2715716 @TomášHübelbauer 谢谢!我已经进行了编辑。 我试图在文档中找到确切的声明,但看起来他们重命名了变量 - prevState 现在只是 state 【参考方案1】:

不,您不应该在 setState 的 updater 函数中改变 prevState。

更新函数必须是纯函数

更新函数被调用两次。看到这个discussion 检查以下 codesandbox 并打开代码框的控制台以查看它的运行情况。

【讨论】:

【参考方案2】:

更简洁的方法是直接引用您要编辑的属性:

doIt = () => this.setState(( [id]: prevValue ) => (
  [id]: !prevValue,
));

【讨论】:

如果[id] 不是state 的直系子代,而是向下一层,是否可以这样做?就我而言,我有一组 [id]s,所有其他 Q/A 和文章都建议复制,但我发现您的解决方案更清晰。 @Al.G.您可能必须使用find 来获取正确的索引来访问正确的数组元素【参考方案3】:

你这样做的方式没有错。修改参数然后返回它是完全可以的。但是,当您根据 prevState 的值修改状态时,使用带有 prevState 参数的 setState,它完全适合您的场景,并且处理它的更简洁的方法是

onSocialClick = e => 
    const id = e.target.value;
    this.setState((prevState, props) => 
        return [id] : !(prevState[id]);
    );
;

【讨论】:

【参考方案4】:

强烈建议不要直接改变状态。此外,您正在改变先前的状态,然后返回它,这没有多大意义。如果您只想在state[id] 处切换状态,则将您的代码修复为更像:

onSocialClick = e => 
    const id = e.target.value;
    this.setState(this.state[id]: !this.state[id);
;

【讨论】:

不鼓励这样做,您应该使用 OP 使用的功能方式(但可能直接使用感兴趣的道具。

以上是关于我可以改变传递给 setState 函数的状态吗?的主要内容,如果未能解决你的问题,请参考以下文章

React 的setState 理解

调用setState时会发生什么?

我的有状态小部件不会更新 ui,即使我正在调用 setState 并将正确的值传递给小部件类

使用 setState 提交后清除表单输入

setState 映射函数中对象的一种状态

反应setState函数和复杂对象[重复]