React-Redux:是不是应该将所有组件状态保存在 Redux Store 中

Posted

技术标签:

【中文标题】React-Redux:是不是应该将所有组件状态保存在 Redux Store 中【英文标题】:React-Redux: Should all component states be kept in Redux StoreReact-Redux:是否应该将所有组件状态保存在 Redux Store 中 【发布时间】:2016-05-21 13:31:33 【问题描述】:

假设我有一个简单的切换:

当我点击按钮时,颜色组件在红色和蓝色之间变化

我可能会通过这样做来达到这个结果。

index.js

Button: onClick=()=>dispatch(changeColor())
Color: this.props.color ? blue : red

container.js

connect(mapStateToProps)(indexPage)

action_creator.js

function changeColor()
 return type: 'CHANGE_COLOR'

reducer.js

switch()
case 'CHANGE_COLOR':
return color: true

但是对于我可以在 5 秒内使用 jQuery、一些类和一些 css 实现的东西,要编写大量代码......

所以我想我真正要问的是,我在这里做错了什么?

【问题讨论】:

react-redux 不作为比 jquery 短的东西出售。它肯定需要一些代码来启动和运行。 【参考方案1】:

Redux 主要用于“应用程序状态”。也就是说,与您的应用程序逻辑相关的任何内容。在它之上构建的视图是该状态的反映,但不必专门使用该状态容器来完成它所做的一切。

只需问这些问题:此状态对应用程序的其余部分是否重要?应用程序的其他部分是否会根据该状态有不同的行为?在许多较小的情况下,情况并非如此。拿一个下拉菜单:它打开或关闭的事实可能不会对应用程序的其他部分产生影响。因此,将其连接到您的商店可能是矫枉过正。这当然是一个有效的选择,但并没有真正为您带来任何好处。您最好使用this.state 并收工。

在您的特定示例中,切换按钮的颜色是否会对应用程序的其他部分产生任何影响?如果它是应用程序主要部分的某种全局开/关切换,它肯定属于商店。但是,如果您只是在单击按钮时切换按钮颜色,则可以将颜色状态保留为本地定义。单击按钮的动作可能具有其他需要动作调度的效果,但这与应该是什么颜色的简单问题是分开的。

一般来说,尽量保持您的应用程序状态尽可能小。你不必把所有东西都塞进去。必要时这样做,否则将某些东西放在那里很有意义。或者,如果它让您在使用开发工具时更轻松。但不要过分强调它的重要性。

【讨论】:

嘿,我知道这个问题永远不会有明确的答案,但我认为你的逻辑在这里非常合理 IMO,这不是完美的答案。这取决于。将 ui 状态存储到反应状态将使 redux 存储干净,但最终会成为难以测试的非功能组件。虽然将 ui 状态存储到 react 状态会增加开发人员的工作量,因为我们必须编写额外的 reducer。但是,有很多包可以帮助您更轻松地将您的 ui 状态存储到 redux 商店,请查看redux.js.org/docs/faq/OrganizingState.html 了解更多详细信息。【参考方案2】:

Redux FAQ: Organizing State redux 官方文档的这一部分很好地回答了你的问题。

使用本地组件状态很好。作为开发人员,您的工作是确定构成您的应用程序的状态类型,并且 每个状态都应该存在的地方。找到适合的平衡点 你,随它去吧。

确定数据类型的一些常用经验法则 放入 Redux:

应用程序的其他部分是否关心这些数据? 您是否需要能够基于此原始数据创建进一步的派生数据? 是否使用相同的数据来驱动多个组件? 能够将此状态恢复到给定的时间点(即时间旅行调试)对您有价值吗? 是否要缓存数据(即,如果它已经存在,则使用状态中的内容,而不是重新请求它)?

【讨论】:

【参考方案3】:

为了突出@AR7 提供的重要链接,并且因为该链接移动了一段时间:

将 React 用于在全局范围内对应用程序无关紧要且不会以复杂方式发生变化的短暂状态。例如,某些 UI 元素中的切换、表单输入状态。将 Redux 用于全局重要或以复杂方式发生变异的状态。例如,缓存的用户或帖子草稿。

有时你会想要从 Redux 状态转移到 React 状态(当在 Redux 中存储一些东西变得笨拙时)或者反过来(当更多组件需要访问一些曾经是本地的状态时)。

经验法则是:做不那么尴尬的事情。

丹·阿布拉莫夫:https://github.com/reactjs/redux/issues/1287#issuecomment-175351978

【讨论】:

【参考方案4】:

这就是 Redux 的问题,开发人员过度设计状态设计,这总是将可能相当简单的应用程序变成复杂的结构。

对我来说,Redux 是一种反应架构,应该在实施之前进行良好的规划和设计。

https://kentcdodds.com/blog/application-state-management-with-react/ “redux 如此成功的原因之一是 react-redux 解决了 Prop-Drilling 问题。通过简单地将组件传递给一些神奇的连接函数,您可以在树的不同部分共享数据,这一事实非常棒。它使用减速器/动作创建者/等。也很棒,但我相信 redux 的普及是因为它解决了开发人员的 Prop-Drilling 痛点。

这就是我只在一个项目中使用 redux 的原因:我经常看到开发人员将他们所有的状态都放入 redux。不仅是全局应用程序状态,还有本地状态。这会导致很多问题,其中最重要的是,当您维护任何状态交互时,它涉及与减速器、动作创建者/类型和调度调用的交互,最终导致必须打开许多文件并跟踪通过你头脑中的代码来弄清楚发生了什么以及它对代码库的其余部分有什么影响。 “”

【讨论】:

【参考方案5】:

是的,值得努力将所有组件状态存储在 Redux 中。如果这样做,您将受益于 Redux 的许多功能,例如时间旅行调试和可重放的错误报告。如果您不这样做,这些功能可能完全无法使用

任何时候在 Redux 中存储组件状态更改,该更改都会从 Redux 更改堆栈中完全丢失,并且您的应用程序 UI 将与存储不同步。如果这对你来说不重要,那么问问自己为什么要使用 Redux?没有它,您的应用程序将不那么复杂!

出于性能原因,您可能希望回退到 this.setState() 处理任何会重复发送许多操作的内容。例如:每次用户键入一个键时,在 Redux 中存储一个输入字段的状态可能会导致性能不佳。您可以通过将其视为事务来解决此问题:一旦“提交”用户操作,将最终状态保存在 Redux 中。

您的原始帖子提到了 Redux 方式是如何“编写大量代码的地狱”。可以,但您可以将抽象用于常见模式,例如本地组件状态。

【讨论】:

改进调试是一个有用的目标,也是 redux 的一个不错的特性,但我认为信噪比也很重要。可以在代码库中记录每个变量,但这会添加大量额外代码,使实际代码更难阅读,并且很难通过日志记录。我认为这同样适用于使用 redux。在 redux 中拥有所有状态可以改进调试,但是额外的代码和抽象会产生成本,这会使代码更难阅读,甚至会使一些调试任务更难。 (而且当 redux 开发工具崩溃时,许多调试收益都会丢失。) 那为什么要使用 Redux 呢?如果你不把所有东西都放在 Redux 中,你就会失去所有的功能,比如 devtools。这真的是全有或全无。如果您将 setState() 用于下拉菜单(如本文的顶部答案),则无法使用 devtools 调试用户在下拉菜单中可能遇到的任何问题。当您将 setState() 用于叠加时,情况会更糟,因为在显示叠加之前和之后无法进行时间旅行。在这里和那里撒上 setState() 很容易出错,因为开发人员必须不断考虑可能会破坏什么。 作为更具体的答复,记录代码库中的每个变量并不是一个有用的隐喻,因为问题在于是使用this.setState() 还是dispatch(action...)。不需要在任何地方都使用this.setState(),但是当你需要时,我的建议是在 99% 的情况下使用 Redux,而基于性能问题,在 1% 的情况下使用 this.setState() 记录每个变量在我看来类似于将所有内容都放在 Redux 中,并且作为一般规则同样不可取。只要状态是分离的,从 Redux 中留下一些东西并不会否定所有 在 Redux 中的特性。 IE。即使选择框的状态不是,我仍然可以调试通过 Redux 传输的 API 调用逻辑。 OP 有一点 - 它需要在多个地方使用更多代码才能使用 Redux,这在他们列出的具体示例中可能是不合理的。 实际上,您可能无法调试您的 API 逻辑。这就是我的观点。很难预见会中断时间旅行的场景,因此最好将所有状态(包括选择框状态)放在 Redux 中,直到出现性能问题。

以上是关于React-Redux:是不是应该将所有组件状态保存在 Redux Store 中的主要内容,如果未能解决你的问题,请参考以下文章

React-Redux 总结

使用 Relay 的嵌套表单组件 UI 中的状态应该在哪里?

组件公共状态管理react-redux

React-Redux

react-redux & 使用useSelector useDispatch 替代connect

react 中的 redux 和react-redux的区别分析