如何理解Redux的Single Source of Truth理念

最近在首页上刷到一个问题

Redux数据流管理架构有什么致命缺陷,未来会如何改进?www.zhihu.com

里面的一些高赞回答,提到了 Redux 的 Single Source of Truth理念是如何的错误。但可惜的是,我认为他们根本就没理解对。

本文就完整地阐述如何理解 Redux的 Single Source of Truth 理念


在官方文档(Three Principles | Redux)中 对 Single source of truth 的整体解释是这样的:

37a7e220d0fb3cf1b7fbc4a786d07e4a.jpeg


本地状态(local state) vs 全局状态(global state)

文档的那句话中,最先应该引起读者注意的是高亮的 global state (全局状态),即 Single Source of Truth 针对的是 全局状态

由此马上该引起我们思考的是——什么样的状态才应该是全局状态
简单看看下面几个例子:

  1. 某个页面里 Dialog(对话框)的打开和关闭状态
  2. 某个页面里的表单的内容
  3. 当前路由
  4. 当前web应用的样式主题的 id
  5. 当前用户的登录状态

个人认为只有3, 4 和 5 应该是全局状态,而 1 和 2 都适合存放在本地状态 —— 判断逻辑其实很简单,即 目标状态是否会关系到 整个APP,是否在大多数页面/组件中被需要

接着看 3,4 和 5 是否都适合放在 redux store 里呢?

很明显 3 是不合适的,因为 当前路由状态 理论上就已经存放在 react-dom-router 的 context 中了,完全没有必要再复制一遍放在 redux store 中 (参考 react-router 的官方文档 React Router: Declarative Routing for React )

4 和 5 在普通场景下是适合放在 redux 供APP全局使用的。

其实早有开发者提出相关的问题了 —— 如何选择是在 Redux store 还是 React state 里存放状态?(Question: How to choose between Redux's store and React's state? · Issue #1287 · reduxjs/redux)

Redux 的祖师爷 Dan Abrammov 是这么回答的:

Use React for ephemeral state that doesn't matter to the app globally and doesn't mutate in complex ways. For example, a toggle in some UI element, a form input state. Use Redux for state that matters globally or is mutated in complex ways. For example, cached users, or a post draft.

Sometimes you'll want to move from Redux state to React state (when storing something in Redux gets awkward) or the other way around (when more components need to have access to some state that used to be local).

The rule of thumb is: do whatever is less awkward.




p.s.

根据上述的内容,我们其实已经可以规避使用一些库了,如 redux-form ,下面的链接是 redux-form 和另外两个主流的 react 表单库 的 npm 下载量对比,可以说是基本凉凉了

formik vs react redux form vs react hook form | npm trends

a89da0dbf084281246c6c22ab6451570.jpeg

(对React 表单库有兴趣的可以查看我的另一篇文章 FreewheelLee:以React表单库Formik为例谈优秀的三方库应该是什么样的 )


One Way Data Binding (单向的数据绑定)+ One Way Data Update Approach (单一数据修改途径)

Single source of truth 不仅仅指单一数据源。

我个人认为,单向的数据绑定 和 单一数据修改途径 也是 Redux的Single Source of Truth理念的一部分

关於单向的数据绑定,React 开发者应该都不陌生,因为这也是 React 的核心理念和最佳实践。简单用一个图阐释

a611e99bb3fb23f9dfafabf7c770f849.jpeg

单向的数据绑定 就是由声明好的视图模板(即React JSX)和 数据模型 生成视图,而视图并不会直接影响/改变 数据模型。

(关于理解 单向的数据绑定 ,可以参考 React 官方文档的 Thinking in React – React )

Redux 也是依照了单向的数据绑定的思想设计的 —— 视图可以监听 redux store 的变化而更新视图,但是不允许视图直接改变 redux store 里的数据和状态。


单一数据修改途径 这个术语是我自己发明的,想表达的意思就是字面意思 —— 有且只有一种途径可以更改数据模型。

在 Redux 中,更新 store state 的唯一推荐方式就是 dispatch action,然后经由 middleware 和 reducer 最后生成新的 store state 。

24e198ca74e57bcf0d08e0319d0114d8.png

单一数据修改途径的设计可以使程序更加可控 —— 既然路只有一条,只需要在这条路上“动手脚”就能影响整个redux数据更新流程,如 打log、修改特定action、添加额外元属性 等等。

在这个层面而言,这也是一种 single source of truth 。

当你把 单一数据源 + 单一数据绑定 + 单一数据修改途径 三点联系起来理解时,你对 Redux 的设计的领悟是否更加透彻清晰了!



Single store vs Multiple store

Single Source of Truth 的这层内容是比较容易理解的,Redux 采用了与 Flux 不同的设计,只允许一个 Store。

单一Store极大地方便了服务端渲染、debug、检查(inspect) 等功能。



后记

最后再分享Dan Abramov的一句话:

b389fadf58c13a36c93ce9ef16baca51.jpeg



分享另一个思考

开头说的那个知乎问题,一些大V的回答获得了大量的赞同,但事实上内容却不一定完全正确。在网上浏览内容时,要保持自己的独立思考,不要盲信、盲从,勤于自己搜索调研不要只做伸手党

推荐我的一篇文章

FreewheelLee:如何阅读技术博客zhuanlan.zhihu.com

(p.s. 我的专栏、我的文章也可能有错误,欢迎读者指出我的错误,共同讨论。)



最后,如果觉得我这本文章对你有帮助、有启发,欢迎 点赞、喜欢、收藏三连!


参考链接:

https://en.wikipedia.org/wiki/Single_source_of_truth

https://medium.com/@dan_abramov/you-might-not-need-redux-be46360cf367

What does the "single source of truth" mean?

Question: How to choose between Redux's store and React's state? · Issue #1287 · reduxjs/redux

Lifting State Up – React


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章