Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

如何选择React状态管理库? #33

Open
BetaSu opened this issue Mar 30, 2022 · 6 comments
Open

如何选择React状态管理库? #33

BetaSu opened this issue Mar 30, 2022 · 6 comments
Labels
JS l1:JS 相关 React l3:React 相关 前端框架 l2:前端框架相关 场景 具体业务场景下的问题 悬赏20元 最佳答题者可以获得20元

Comments

@BetaSu
Copy link
Owner

BetaSu commented Mar 30, 2022

发生问题的场景

小明刚开始使用React,面对众多的状态管理库(Redux、MobX、Recoil、Zustand、Jotai、valtio...)他有点不知所措

需要解决的问题

你能从以下角度帮他分析如何做状态管理库的选型么?

  1. 从业务规模角度分析(自己的练手项目、几个人参与的一次性的小项目、团队参与的长期维护的大项目...)
  2. 从管理的状态类型分析(与用户交互相关的状态、服务端请求回的数据...)
  3. 从应用类型分析(普通活动页、富文本编辑器...)
  4. 其他角度(比如普及度、上手难度)

最佳答案评选标准

请从以上角度有条理作答,细致而全面的答案是加分项

最佳答案

悬赏中,欢迎作答...

答题同学须知

  • 答题规范:请在一次评论中完成作答,后续修改也请编辑该评论,而不是追加新的评论

  • 评选标准:最佳答案由围观同学的 👍 和卡颂共同决定

  • 评选时间:一般是问题发布24小时后评选,如果问题发布当天回答数较少,问题悬赏金额可能增加,同时悬赏时间也会增加

围观同学须知

  • 对于你满意的答案,请不要吝惜你的 👍,这是评选最佳答案的依据

  • 非答题的评论会被删除,问题相关讨论请在赏金猎人群中进行

@BetaSu BetaSu added JS l1:JS 相关 React l3:React 相关 悬赏10元 最佳答题者可以获得 10 元 场景 具体业务场景下的问题 前端框架 l2:前端框架相关 悬赏15元 最佳答题者可以获得 15 元 and removed 悬赏10元 最佳答题者可以获得 10 元 labels Mar 30, 2022
@kairos1874
Copy link

kairos1874 commented Mar 31, 2022

(重点提示一下:有意思的是,Zustand、Jotai、valtio 基本都出自dai-shi 大佬之手,嘿嘿,发现什么了没,也许你顺着这条线索就已经可以找到题目的答案了,我下面的文字也不需要看了)

最近刚好在解决项目里面滥用 redux 的问题,来凑一下热闹。先声明一下,我不打算直接回答题目本身,以下所有观点也仅代表目前的一些杂乱的思绪,文字看起来也会比较乱,但也都是来自实际的业务一线的一些思考,也不一定逻辑正确。

怎么说呢,这个问题需要写一篇很长很长的文章了,现版本的 react 的状态管理不能一概而论认为该采用什么第三方库,而是要回归本质的思考状态,先简单描述一下吧(以下只针对 function component,class component 也该退出历史舞台了):

1、要搞懂这个问题,首先要去深刻理解 hook 的 useState,以及 function component 的 re-render 机制(这个很重要,因为状态管理必须围绕着这个展开,也就是状态的更新怎么触发组件的更新),需要注意的是,function component 和 react 以前的 class component 从理念上是有很大差别的,包括其组件的 re-render 机制。

2、要搞懂 mutable 和 immutable,是的,这特别重要,因为现在版本的 react 处处强调 immutable 的重要性,包括 state,props,context,useEffect、useCallBack 的 deps 等。我记得 Dan Abramov 在字节的采访中说过:Vue 在不断探索我们可以用 mutability 做什么,而 React 在不断探索 immutability 能够做到的事。(ps:redux 是 immutable 的,mobx 是 mutable 的,同时必须得安利一下 immer 这个库:Immer simplifies handling immutable data structures)

3、搞懂 Context API,和它的适用场景,还有 Context 用作状态管理的话,其实是不太够的,目前 Context 存在的问题:如果用的不合理会引起很多不必要的渲染,比如 Context 的 value 用了大对象。然后理解什么场景该用 state,什么场景该用 Context。虽然 Context 有不足的地方,但有些状态管理库底层会用 Context,或者在使用层面会涉及到怎么和 Context 结合,搞清楚 Context API 的原理能帮助你很好的理解其他的状态管理库。知乎上的这个问题可以读一下,这个回答下面的几位大佬其实已经讲了 Context 的局限性,还有怎么合理的使用和优化它,感兴趣的可以细读一下 https://www.zhihu.com/question/450047614
(当然了,有人说用 Context + useReducer 也可以实现状态管理,其实是可以的,没毛病,但是呢,由于 Context 的局限性,其实这种方案也是不太够的,用的不好依然有不必要的渲染的问题。具体看我上面贴出来的知乎的链接里的讨论)

4、选择合适的数据结构去定义state(在react里面一定要注意 immutable data structure 的更新问题),学会合理组织 state,这一点也特别重要,具体可以看 react 新文档的这一节
https://beta.reactjs.org/learn/choosing-the-state-structure
这一点告诉我们,数据结构还是重要啊

5、学会自定义 hook 去抽离通用的逻辑,然后知道什么场景该抽离 hook

6、要合理的封装组件(特别是要分清组件的 state 和 props 的职责,这个也许需要大量的实践,但你可以从软件的 API 设计的角度出发去考虑)

7、学会处理异步数据请求,具体可以看这篇文章 https://www.robinwieruch.de/react-hooks-fetch-data/

8、关于 hook 背景下的状态管理的一些问题,推荐关注一下dai-shi 大佬的主页和他的博客,他是是 use-context-selector、react-tracked、jotai、zustand、valtio的作者,同时对于状态已经状态管理有很深的理解(别误会,不是列出一堆东西,让大家再次陷入技术选型的漩涡,而是从大佬的作品和思考中获得启发,从而得到自己的理解)

ok,深刻搞清楚了以上的这些点,然后才会来到我们的状态管理。为什么这样讲呢,因为很多场景其实要合理的拆分组件,合理的去定义和组织组件的 state 和 props,合理的抽离 hook,合理的处理好异步数据,这才是做好状态管理的前提,而不是一上来就什么都塞到集中式的 Store 里面去。而且从我这几年看到的实际项目中的场景来看,确实是很多人没搞清楚这些,然后把状态一股脑的塞到 redux 里面,这样就带来了很多问题了。这些问题包含了 redux 文件的膨胀和繁杂的模版代码,state 和 props 职责的不清晰,异步数据的处理的混乱,state 的数据结构使用的不合理,从而导致项目充斥着各种胶水代码,等等等。当然了,就算不用 redux,用其他的库也是一样的。

如果对以上的概念不熟悉的,推荐大家好好认真的读一下 react 的新文档:https://beta.reactjs.org
如果完整的读一遍,并且把文档的每个 demo 都好好跑一遍,应该会有不一样的认识

然后我们的焦点才来到状态管理的问题,什么 redux,mobx,Recoil,redux toolkit,hox,zustand 等等等。。。这个讲起来又要涉及到很多东西了,比如
1、状态机,单向数据流,响应式, immutable和mutable,函数式和oop,原子化,集中式状态管理,发布订阅者模式(是的,题目里列出来的这几个库,要搞清楚它们之间的区别都或多或少的涉及到这些乱七八糟的概念)
2、什么场景应该用内聚的 state,什么场景仅仅用 Context 就可以了,什么逻辑该抽离成 hook(自定义的hook是可以包含状态的),全局的状态和局部组件的状态该怎么做。
3、状态和行为怎么合理的一起封装,然后状态更新后怎么通知组件的更新
4、怎么处理异步
5、状态管理基本都围绕着这些问题展开,理清楚之后,才能做到手中无剑,心中也无剑,回归初心,化繁为简在不同的业务场景选择合适的方式(因为有些状态管理库的模版代码或者 API 真的很多,非常很容易让人迷失其中)
6、甚至你可以封装自己的状态管理库
7、等等等。。。

好了,废话有点多,随性而写的,可能文字也比较乱,我也没有给出答案(因为我自己也还差一些才能把思路捋清楚),但其实我是希望大家能回归本质的去思考状态和状态管理,而不是迷失在选择哪一个库,或者武断的认为就该怎样和不该怎样,这世界有时候没有标准答案,只有认知的不一样,对生活的理解不同,就会有不一样的人生,无所谓对错,但确实存在着特定的场景下某种方式也许更合理。

先占个坑位,如果有大佬愿意提高一下悬赏金额,我可以考虑抽空把更详细的文章(1w字以上吧)写出来,由浅入深的讲讲这些问题(最近实在太多事情要做了,穷啊,没钱没动力码字啊)


2022.5.7更新:
最近有不少同事问 recoil、jotai ,和 mobx、redux 怎么选择。怎么说呢,原子化和状态聚合是两种不同的方式,而且完全可以共存。recoil、jotai 的这种原子化的方式,api 类似 useState,容易上手。而 mobx、redux 的这种叫状态聚合的方式。如果你的应用是数据驱动的,或者对数据结构要求比较高的,那么状态原子化是不够的,必然要走到状态聚合的方式上去。而 redux 和 mobx 呢,我个人是更推荐 mobx,或者类 mobx 的方案,原因很简单,mobx 对多样性的自定义的数据结构兼容更好,如果你是个有追求的程序员,那么在复杂的数据驱动型的应用里面,必然会涉及到很多自定义的数据结构。而且在 js 里面, mutable 的数据结构的代码,天然就比 immutable 的数据结构的代码更清晰,也更容易理解(当然了,你也可以借助 immer 来降低 immutable 数据结构的操作成本,但依然是要啰嗦一些)

@handsomeCarl
Copy link

https://zhuanlan.zhihu.com/p/475785123 这位博主总结的很好

@bigbigDreamer
Copy link

https://zhuanlan.zhihu.com/p/475785123 这位博主总结的很好

当他说Recoil难用的时候,这篇文章就已经被 Pass

@BetaSu BetaSu added 悬赏20元 最佳答题者可以获得20元 and removed 悬赏15元 最佳答题者可以获得 15 元 labels Apr 6, 2022
@LadyChatterleyLover
Copy link

  1. redux和react-redux,老牌react状态管理,但操作麻烦,发送异步请求需要借助中间件(react-thunk或者react-saga),不能直接发送异步请求,没有提供命名空间,各个模块需要注意命名,内部原理为发布订阅,有点消耗性能,提供了类组件和函数组件两种用法,适合入门学习。
  2. dva,基于react-saga封装,提供了redux所有操作,并且集成了异步请求和命名空间,不过需要会es6迭代器语法或者已经会react-saga的开发者,如果你的项目是采用umi,umi自带dva,将是最好的选择。不过个人觉得dva和vuex很像,如果你是一名vue开发者,相信dva很快能上手。适合大型项目,有结构的组织你的状态管理。
  3. recoil,facebook新推出的状态管理库。上手简单,主要api也就是atom和selector两个,而且主打高性能,提供每个数据唯一key,避免数据污染,不过目前只支持函数组件,不支持类组件。

@specialbiscuit
Copy link

https://juejin.cn/post/6986816997329731614 可以参考下

@imondo
Copy link

imondo commented Sep 30, 2022 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JS l1:JS 相关 React l3:React 相关 前端框架 l2:前端框架相关 场景 具体业务场景下的问题 悬赏20元 最佳答题者可以获得20元
Projects
None yet
Development

No branches or pull requests

7 participants