为什么使用redux进行不可变状态

Baz*_*Baz 9 redux

我正在学习redux并且正在努力理解为什么国家必须是不可改变的.你能否提供一个例子,最好在代码中,打破不可变合同导致不那么明显的副作用.

mar*_*son 12

Redux最初的发明是为了展示"时间旅行调试"的想法 - 能够在调度动作的历史中来回走动,并看看每个步骤的UI是什么样的.另一个方面是能够实时编辑代码,重新加载它,并在给定新的reducer逻辑的情况下查看输出的外观.

为了能够在状态之间来回切换,我们需要确保减速器功能没有副作用.这意味着需要不可变地应用数据更新.如果reducer函数实际上直接修改了它的数据,那么在状态之间来回踩踏将导致应用程序以意想不到的方式运行,并且将浪费调试工作.

此外,React-Redux库依赖于浅等式检查来查看组件的传入数据是否已更改.如果数据引用相同,则生成的包装器组件connect假定数据未更改,并且组件不需要重新呈现.不可变数据更新意味着创建了新的对象引用,因此connect将看到数据已更改且UI需要更新.

  • 当然。新的 [Redux FAQ section on Immutable Data](http://redux.js.org/docs/faq/ImmutableData.html) 提供了更多关于 Redux 在哪里以及如何依赖不变性的信息。 (2认同)

Rem*_*sen 6

两个想法

您需要了解有关不可变性的两个想法:

  • 只在减速器中改变状态
  • 使用不可变的数据结构

只在减速器中改变状态

Redux尝试确保您只改变Reducers中的状态.这很重要,因为它更容易考虑您的应用程序数据流.

假设某个值未按预期显示在UI中,或者应该更改的值仍显示其原始值.

在这种情况下,你可以考虑哪个减速器导致突变,看看出了什么问题.

这使得思考Redux问题变得非常简单,并使开发人员高效工作.

有时您可能会错误地改变视图或动作中的状态.如果你考虑生命周期:

Action -> Reducer -> Views-> Action 
Run Code Online (Sandbox Code Playgroud)

如果状态在视图中发生更改,然后触发操作,则可以覆盖状态更改.这将很难找到开发人员正在发生的事情.我们通过仅在reducers中改变状态来解决这个问题.

注意:另一个好处是reducers是纯函数,所有async东西都在actions/middleware中.因此,所有副作用都发生在动作/中间件层中.操作是我们与外部世界的连接(HTTP,本地存储等).

使用不可变的数据结构

正如我已经提到的,有时你可能会错误地改变视图或动作中的状态.为了减少这种情况发生的可能性,我们可以通过使用和不可变数据结构使状态突变显式化.

使用不可变数据结构也具有性能优势,因为我们不需要执行深度相等检查来检查突变.

最常用的不可变数据结构提供者是immutable.js.