为什么纯 reducer 在 redux 中如此重要?

Why are pure reducers so important in redux?

纯减速器没有副作用,可以实现时间旅行等功能。它们使对应用程序行为的推理变得更容易。

这对我来说很直观。但我无法阐明为什么纯 reducer 会导致这些积极的非功能性属性。

有人能帮我阐明为什么让 reducer 没有副作用会更容易推理应用程序行为吗?

是不是因为在 运行 个 reducer 之后保证你有完全相同的状态?

如果是这样,那么即使是有副作用的(即非纯的)reducer 肯定也有这个 属性?

Is it because you are guaranteed to have the exact same state after running the reducers?

是的,pure reducer 是 deterministic,这意味着如果给它们相同的输入,它们将始终产生相同的结果输出.这 属性 有助于单元测试等情况,因为您知道如果测试通过一次,它将永远通过。

If so, surely even side-effectful (ie. non-pure) reducers could have this property?

不,不纯的 reducer 会同时依赖应用程序的 输入 状态 。在您测试时,它们可能以给定方式运行 1000 次,但当您的应用程序恰好处于您从未想过要测试的特定状态时,它们就会中断。

当然,您的单元测试中完全有可能存在漏掉极端情况的漏洞。但是,如果测试结果 100% 基于 输入 ,那么您只需查看减速器预期的规定输入,就更有可能注意到这些极端情况。

如果一个函数改变了应用程序的状态,那么 运行 同一个函数两次,或者相同的几个函数以不同的顺序,可能会导致完全不同的行为。这使得很难推断应用程序的正确性,因为为了知道给定的代码行是否正确,您必须知道在调用它之前发生了什么,可能是在应用程序的完全不同的部分。

Is it because you are guaranteed to have the exact same state after running the reducers?

是的,这就是使纯减速器成为 "gold standard" 的原因。如果输出只依赖于输入,那么测试、回放、保留历史记录等都非常容易...

If so, surely even side-effectful (ie. non-pure) reducers could have this property?

(不是流行的答案)。这也是正确的。如果您小心的话,非纯减速器也可能具有这些相同的属性。但是,它更容易出错,并且(从概念上)这样做没有多大意义。 (我认为)你的想法是一切都只是输入和输出。您可以稍微改变一下思路,将 "non-pure" 减速器的内部状态视为减速器的另一种输入。

从这个意义上说,您可以想象跟踪您的应用程序状态、您的操作和您的 reducer 的内部状态,并最终得到相同的播放等,您的纯 reducer 的属性(尽管您需要一个更多代码来处理它)。

但是,问题来了:现在您有了实际的应用程序状态和 reducer 的内部(和隐藏)状态。谁想跟踪两组状态?这才是真正使测试、推理和实施更加困难的原因。有更多"kinds" 的事情需要跟踪,并且更容易miss/forget 关键细节。从本质上讲,如果您的应用程序已经有很大一部分专门用于跟踪状态,为什么您 想要 将更多状态隐藏在您的 reducer 中?

因此,即使忽略为了 "rightness" 而做正确的事情,从概念上讲,将所有状态都放在一个地方对整个系统架构来说更简单。