Reactjs Redux:为什么避免突变是使用它的一个基本部分?

Reactjs Redux:为什么避免突变是使用它的一个基本部分?,reactjs,redux,Reactjs,Redux,我是Redux新手,我真的在努力了解使用函数式编程使单向数据更加优雅的大局 在我看来,每个reducer都采用旧状态,在不改变旧状态的情况下创建一个新状态,然后将新状态传递给下一个reducer以执行相同的操作 我明白,不产生副作用有助于我们获得单向数据流的好处 我真的不明白不改变旧状态有什么那么重要。 我唯一能想到的可能是我读到的“时间旅行”,因为如果你坚持每一种状态,你可以执行和“撤销” 问题: 我们不想在每一步都改变旧状态还有其他原因吗?如果操作得当,使用不变的数据结构可以对性能产生积极影

我是Redux新手,我真的在努力了解使用函数式编程使单向数据更加优雅的大局

在我看来,每个reducer都采用旧状态,在不改变旧状态的情况下创建一个新状态,然后将新状态传递给下一个reducer以执行相同的操作

我明白,不产生副作用有助于我们获得单向数据流的好处

我真的不明白不改变旧状态有什么那么重要。

我唯一能想到的可能是我读到的“时间旅行”,因为如果你坚持每一种状态,你可以执行和“撤销”

问题:


我们不想在每一步都改变旧状态还有其他原因吗?

如果操作得当,使用不变的数据结构可以对性能产生积极影响。对于React,性能通常是为了避免在数据没有更改的情况下不必要地重新呈现应用程序

要实现这一点,您需要将应用程序的下一个状态与当前状态进行比较。如果状态不同:请重新渲染。否则不要

要比较状态,需要比较状态中的对象是否相等。在普通的旧JavaScript对象中,需要进行深入比较,以查看对象中的任何属性是否发生了更改

对于不可变对象,您不需要这样做

immutableObject1 === immutableObject2
基本上就是这样。或者,如果您正在使用类似Immutable.js的库
Immutable.is(obj1,obj2)

就react而言,您可以将其用于
shouldComponentUpdate
方法,就像流行的
PureRenderMixin
一样

shouldComponentUpdate(nextProps, nextState) {
    return nextState !== this.state;
}
当状态未更改时,此函数可防止重新渲染

我希望,这有助于不可变对象背后的推理。

我对Redux(和React.js)也很陌生,但这是我从学习这些东西中了解到的

选择不可变状态而不是可变状态有几个原因。 首先,突变跟踪是相当困难的。例如,当您在多段代码中使用一个变量,并且该变量可以在每个地方修改时,您需要处理每个更改并同步变异结果。 这种方法在许多情况下会导致双向数据流。数据片段在函数、变量等之间上下流动。代码开始被负责处理状态更改的if-else构造污染。 当您添加一些异步调用时,您的状态更改可能更难跟踪。 当然,我们可以订阅数据事件(例如
Object.observe
),但这可能会导致应用程序中某些未完成更改的部分与程序的其他部分不同步

不可变状态帮助您实现单向数据流,从而帮助您处理所有更改。首先,数据从上到下流动。这意味着应用于主模型的所有更改都将推送到较低的组件。您可以始终确保应用程序的所有位置的状态都是相同的,因为它只能从代码缩减器中的一个位置更改。 还有一件事值得一提——您可以在多个组件中重用数据。状态无法更改(可以创建一个新的状态),因此在多个位置使用相同的数据段是非常安全的

您可以在这里找到更多关于可变性利弊的信息(以及选择它作为Redux主要方法的原因):


    • 没有理由。没有任何根本原因表明shouldComponentUpdate“纯渲染”优化无法处理可变状态容器。例如,这个图书馆就是这样做的

      对于不可变数据,对数据结构本身的引用可以用作版本标记。因此,比较引用就是比较版本


      对于可变数据,您需要引入(并比较)单独的版本标记,这很难手动实现,但可以通过智能“可观察”对象轻松实现。

      Redux通过比较两个对象的内存位置来检查旧对象是否与新对象相同。如果在减缩器中变异旧对象的属性,“新状态”和“旧状态”都将指向同一个对象,Redux将推断没有任何变化。

      无变异”咒语的关键是,如果不能变异对象,则必须创建一个新对象(使用原始对象的属性加上新对象的属性)

      要在调度操作时更新组件,Redux检查对象是否不同,而不是属性是否已更改(这要快得多),因此:

      • 如果创建一个新对象,Redux将看到该对象不同,因此它将触发组件更新
      • 如果对存储中已存在的对象进行变异(例如,添加或更改属性),Redux将看不到更改,因此不会更新组件

      到目前为止,这是对问题核心的最佳答案。正如我所说:“我明白了,不产生副作用有助于我们获得单向数据流的好处。**我真的不明白不改变旧状态有什么那么重要。**为什么这不是公认的答案?简言之,如果您对对象进行变异,则无法进行以下比较:immutableObject1===immutableObject2。相反,您必须执行深度比较,以查看对象内的任何属性是否发生了更改。我真的没有得到参数。如果我在不使用reduce的情况下更改了状态变量r作为一个纯函数,组件的呈现调用的数量不等于i