为什么redux需要不可变状态

为什么redux需要不可变状态,redux,immutable.js,Redux,Immutable.js,在我的redux存储中,我的状态是Immutable.js类型,我只在我的还原器中更改状态。如果跳过使用immutable,让解析器在命令上检查我的应用程序,并在我在reducer函数之外更改存储时发出警告,这不是更有意义吗?或者有没有一个好的理由来解释为什么不这样做 如果你愿意,你可以在你的还原子中改变你的状态。Redux并不要求您不改变您的状态,但它建议您不要这样做 React-Redux不是Redux,它的设计假设状态永远不会发生变化。这使它能够进行非常快速的检查,以确定状态层次结构中是否

在我的redux存储中,我的状态是Immutable.js类型,我只在我的还原器中更改状态。如果跳过使用immutable,让解析器在命令上检查我的应用程序,并在我在reducer函数之外更改存储时发出警告,这不是更有意义吗?或者有没有一个好的理由来解释为什么不这样做

如果你愿意,你可以在你的还原子中改变你的状态。Redux并不要求您不改变您的状态,但它建议您不要这样做

React-Redux不是Redux,它的设计假设状态永远不会发生变化。这使它能够进行非常快速的检查,以确定状态层次结构中是否有更改

Redux本身将在每次处理操作时触发事件,无论它是否修改(通过修改或替换)状态。它从不检查状态,除非
未定义
。它不在乎你用它做什么

不可变状态有很多好处,但在Redux中使用的主要好处是可以快速检查修改。例如,您的“解析器”每次运行时都需要访问整个状态中每个对象和数组的每个属性和项,以便做出有意义的确定。如果React Redux做了同样的事情,那么它会非常慢,没有人会使用它


因此,成千上万的开发人员将自己限制在不可变的范围内,因为它具有学术以外的真正优势。

这个问题有几个方面:

  • Redux鼓励您为简化程序编写纯函数。这将启用时间旅行调试等功能,并使它们更易于测试。“纯”表示没有副作用,这意味着您不应该直接修改传入的任何数据。相反,数据更新应该是不可变的(即,通过复制要更新的部分数据)
  • React-Redux的
    connect
    函数假定更新将不可变地完成,并进行引用比较以查看传入数据是否已更改。如果对象引用与以前相同,则假定没有任何更改,并且不会导致组件重新渲染
但是,请注意,“不可变更新”并不意味着您必须使用immutable.js库。完全可以以不变的方式更新普通JS对象


我有许多关于这些主题的有用文章的链接,这是我工作的一部分。具体请参见和的类别。我还有另一个页面,列出了各种各样的工具,包括使更新普通JS数据更容易的实用程序。最后,我有一个列表,其中包括一些工具,如果您意外地改变了您的状态,这些工具将向您发出警告。

我认为您提出的某种类型的中间件,可以检查无意中的状态变化,实际上是一个非常酷的想法。我不确定它的可行性/性能(它甚至可能已经存在,我只是没听说过)。但是,对于那些不使用诸如Immutable.js或Immutable之类的库的用户,我可以看出这是多么有用

我只是想澄清,Immutable.js强制要求您不要改变您的状态,这只是一个结果,即不可能从减缩器外部更改您的状态。通用的不变性编程概念和特定于Redux的仅使用减缩器来更改状态的概念之间有一个重要的区别。Immutable.js强制前者,因此逻辑上也强制后者

然而,Immutable.js确保您不会意外地改变状态,这并不是将库用于Redux存储的唯一原因:

  • 性能:Immutable.js具有性能优化,允许它在实际共享内存中相同的底层对象的同时强制实现不可变性。这意味着您不会仅仅为了更改数组中的单个项而对大量数据执行深度复制。这意味着,在存储有大量数据和/或状态发生许多变化的情况下,内存占用会显著减少
  • 助手方法:虽然可以使用各种技术来避免状态突变,但Immutable.js有一个非常好的API来实现这一点。例如,如果您曾经尝试过更改深入嵌套在数组和/或对象中的内容,您会注意到使用本机JS进行更改是非常痛苦的。js使您可以轻松地深入到您想要的深度,更改某些内容,并将这些内容链接在一起
也就是说,这绝对是可选的。您可以选择前面提到的无缝不可变、lodash fp,并且只需手动执行即可:

return Object.assign({}, state, { name: 'new name' });
作为比较,Immutable.js的替代方案是:

return state.set('name', 'new name');

如果你不想依赖immutable.js,你可以在你的简化程序中使用and。问题是更新冻结对象变得单调乏味,特别是对于嵌套对象,例如object.assign({},freezedObj,{a:1,b:object.assign({},freezedObj.b,{c:2}));您可以签出,这是一个轻量级的不可变帮助程序,可以简单地执行上述任务。
return state.set('name', 'new name');