Redux 动作/reducers 与直接设置状态

Posted

技术标签:

【中文标题】Redux 动作/reducers 与直接设置状态【英文标题】:Redux actions/reducers vs. directly setting state 【发布时间】:2016-11-12 00:24:54 【问题描述】:

我是 Redux 的新手。我无法理解动作和减速器与直接修改商店的组件的价值。

在 Redux 中,您的 React 组件不会直接更改存储。相反,它们会发送一个动作——有点像发布一条消息。然后一个 reducer 处理这个动作——有点像消息订阅者——并改变状态(更准确地说,创建一个新状态)作为响应。

我觉得类似 pub/sub 的交互增加了间接层,这使得更难理解组件实际在做什么——为什么不直接让组件将新状态传递给 Redux 存储呢?将this.props.setReduxState 之类的东西注入到 React 组件中会不会是一件坏事?

我开始理解为什么状态本身需要不可变的价值(相关问题 -- Isn't Redux just glorified global state?),与检查更新以查看哪些组件道具需要更新以响应状态变化有关。我的问题是额外的 action/reducer 层与直接操纵商店。

【问题讨论】:

可预测性,在我看来是值得的。你看过mobx吗?这听起来像你的小巷github.com/mobxjs/mobx 通常你会希望一个动作在它到达reducer并创建一个新状态之前通过一个中间件链。您甚至可能希望阻止某些操作影响减速器。这对于诸如权限检查和异步任务之类的事情特别有用。 【参考方案1】:

在开发过程中,您经常需要知道以及如何改变了状态。通过发出动作来改变状态可以让你保留这些问题的答案。

动作是告诉存储应该如何修改它的信息的有效负载。此信息以普通 javascript 对象的形式表示,允许记录、序列化和存储此信息。由于所有历史都被“记住”,您可以稍后重放所有操作链以进行调试或测试。结合Redux DevTools 之类的工具,它使开发过程变得非常简单和令人惊叹。由于所有商店修改都记录到监视器,因此您可以看到如何何时在每个步骤中修改了状态。更重要的是,您可以通过动作链向后或向前。

将所有突变集中在一个地方的另一个好处是更容易控制状态。这保证了所有突变都以严格的顺序一一发生,并且没有回调可以使应用程序行为不稳定。它还允许将某些操作常用的功能保存在一个地方,或者换句话说,应用中间件。

【讨论】:

【参考方案2】:

当我决定进入 Redux 兔子洞时,我遇到了一些非常相似的问题。就我而言,我只使用 React 内部状态来开发相对较小的应用程序和组件,它仍然运行良好。只有当应用程序和组件的数量变得更大时,setState 才变得有些笨拙。

我认为这一点没有得到足够的强调 - 如果您正在开发一个相对较小的应用程序或一些足够容易跟踪但没有强大的不可变存储解决方案的组件,您不必总是使用 Redux .刚开始就有很多必要的样板文件,在某些情况下可能会非常耗时。

话虽如此,React + Redux 是一个很好的设计范式,一旦你习惯了它并拥有你自己可以调用的样板文件,你就可以遵循它。 Redux 本质上偏爱 props 而不是 state,这会强制不可变设计,因为您(通常)不能改变 props。这就是使 Redux DevTools “时间机器”成为可能的原因,以及其他人之前提到的所有可以扔到商店的中间件。

中间件是其中的重要组成部分,尤其是随着更精确的同步和异步任务解决方案的出现,比如 redux-saga (https://redux-saga.js.org/)。当你刚开始时,IMO “thunks” (https://github.com/gaearon/redux-thunk) 比 sagas 更容易理解,除非你已经是生成器方面的专家,但 sagas 更容易预测,因此从长远来看是可测试的。

因此,您可以使用一组操作/reducer,而不是为每个组件设置单独的内部状态,因为您知道您不会错误地改变状态。我发现 ImmutableJS (https://facebook.github.io/immutable-js/) 和 Reselect (https://github.com/reactjs/reselect) 的组合,它为您提供了可组合的选择器 - 非常适合这个。不需要Object.assigns 或大量的传播运算符,它会为您创建一个新对象。

我不会急于将现有的非 Redux 项目转换为 Redux,工作流程的不同足以引起严重的混乱,但是您很难找到尚未拥有的新项目的样板Redux 在他们的工作流程中。比如“React Boilerplate”(https://github.com/react-boilerplate/react-boilerplate),我知道这种方式一开始让我大吃一惊,但绝对值得一试。它确实测试了您的函数式编程能力。

【讨论】:

以上是关于Redux 动作/reducers 与直接设置状态的主要内容,如果未能解决你的问题,请参考以下文章

reducer.state.props 在嵌套动作 react/redux 中未定义

在 redux 中使用样板动作和 reducer

所有的 redux 动作都应该有相应的 reducer 吗?

Redux:使用 Redux 更新数组的状态

Redux:重用reducer来更新多个状态属性

Redux For SwiftUI