选状态管理库总纠结?一个三维决策框架帮你定方案
选状态管理库这件事,最怕的不是「选错了」,而是「选的时候根本没想清楚自己要什么」。所以这篇不会给你一个放之四海皆准的推荐,而是给一个三维决策框架——项目规模、团队经验和性能需求——让你自己就能快速收敛到 2-3 个候选方案,然后做最后权衡。
先把候选池缩小:这三类库解决的是不同层级的问题
React 生态里的状态管理方案看着多,但按职责分层之后其实只有三类:全局 Store 型、原子型、以及数据同步型。每一类解决的核心问题不同,混在一起比本身就是错的。
全局 Store 型(Redux / Zustand)的本质是「应用级单一数据源 + 可预测的状态变更」。如果你的状态之间有强关联、需要跨组件共享且更新逻辑复杂,这类库最合适。Redux Toolkit 在 2024 年的使用率仍然很高,npm 周下载量稳定在 1000 万级别,但它的样板代码问题已经被 RTK 的 createSlice 和 createAsyncThunk 大幅削减。Zustand 则在轻量全局 Store 这个细分里做到了极致,v5 版本的包体积只有 1.1kB gzipped,API 设计极其简洁,基本就是 create 一个 hook 完事。
原子型(Jotai / Recoil)解决的是「组件级状态依赖」问题。你的状态天然是分散的、独立的原子,组件按需订阅,更新时只重渲染真正依赖了那个原子的组件。Recoil 的痛点在于 Facebook 不再积极维护,2024 年之后基本处于半弃坑状态,所以现在聊原子型方案,Jotai 已经是事实上的首选。它的 atom 和 derived atom 模型非常适合细粒度更新场景,比如一个复杂表单里十几个字段各自独立、又需要按规则联动。
数据同步型(React Query / SWR)严格来说不是「状态管理库」,是「服务端状态缓存层」。如果你的状态主要来自 API,大部分「全局状态」其实只是服务端数据的客户端镜像,那用 React Query 或 SWR 管理这些数据,剩下的纯客户端状态用 Context + useReducer 或者一个小型 Store 就够了。很多团队硬上 Redux 的根本原因是没区分清楚「服务端状态」和「客户端状态」——Redux 官方在 2023 年的文档里也明确建议,如果你主要是做数据抓取和缓存,应该优先考虑 React Query 这类工具。
维度一:项目规模——不是「大项目用 Redux」,而是看状态的复杂度
「大项目用 Redux,小项目用 Context」这句话已经过时了,而且有误导性。项目规模这个维度真正要评估的,不是代码行数或页面数量,而是状态的交织程度和更新频率。
如果你的应用里,大部分页面是独立的、各自加载自己的数据、页面之间不需要共享除用户信息之外的全局状态,那项目再大也不需要 Redux。用 React Query 管理服务端数据,用 Zustand 或 Context 存一份用户 token、主题偏好,就够用了。Shopify 的 Hydrogen 框架就是个例子——基于 React 18 的 Server Components,状态管理被极大地简化,很多以前必须在前端全局 Store 里维护的东西现在直接走服务端。
反过来,如果你的应用只有 20 个页面,但每个页面都在操作同一批核心数据——比如一个在线表格编辑器或 BI 看板,编辑操作需要 undo/redo、需要多人协作的冲突处理、需要精确追踪每个字段的变更——那 Zustand 的轻量反而成了短板,Redux 的中间件生态(特别是 redux-saga 或 RTK Query 的缓存策略)和 DevTools 的时间旅行调试能力才有用武之地。这种场景下,即使项目代码量不大,状态的复杂度也足以支撑 Redux 的引入成本。
一个实用的判断标准:如果你能在 5 分钟内画出整个应用的状态依赖图,且节点不超过 15 个,那一定不需要 Redux。 如果画不出来,或者画出来之后箭头交叉得像毛线团,那 Redux 的结构化约束反而是帮你理清逻辑的工具。
维度二:团队经验——学习曲线和「能招到人」是两回事
团队经验这个维度,拆开来看其实包含两层:现有团队的学习成本,和未来招人的市场供给。
Redux 的学习曲线确实陡——不是因为 API 复杂(RTK 已经很简洁了),而是因为它强制了一套思维模型:action、reducer、middleware、immutable update。这套模型的价值在于强约束带来的可维护性,代价是新人上手的摩擦。如果你的团队里有两三个熟悉 Redux 的老人带着,新人能在 1-2 周内上手;如果整个团队都没有 Redux 经验,第一个项目大概率会写出大量反模式代码,反而比不用 Redux 更乱。
Zustand 和 Jotai 这类库的学习成本低得多。Zustand 的 API 基本就是 React hooks 的延伸,会用 useState 就差不多会用了。Jotai 的原子模型需要理解一下 atom 和 useAtom 的关系,但整体心智负担远小于 Redux。对于创业团队或快速迭代的项目,选低学习成本的方案是理性的。
但从招人角度看,Redux 在市场上的存量开发者远多于 Zustand/Jotai。根据 2024 年 Stack Overflow 开发者调查,React 生态里 Redux 的使用率仍然排在第一梯队。如果你的公司需要快速扩张前端团队,选 Redux 意味着候选人池子更大。不过这个优势正在缩小——Zustand 的 npm 周下载量在 2024 年 Q4 已经超过了 500 万,增长曲线很陡,未来两年市场供给的差距会持续收窄。
维度三:性能需求——大部分场景下的性能问题不是库的问题
性能这个维度最容易过度焦虑。React 18 的并发特性(Concurrent Rendering)和自动批处理(Automatic Batching)已经帮我们解决了大量重渲染问题。在大部分业务场景下,选 Zustand、Jotai 还是 Redux,对最终性能的影响差异不大——真正影响性能的是你的状态结构和组件拆分方式。
但确实存在一些场景,状态管理库的选择会直接决定性能天花板。如果你的应用有高频更新的需求——比如实时协作的 Canvas 画布、金融行情看板、每秒几十次状态变更——那原子型方案的优势就体现出来了。Jotai 的细粒度订阅机制意味着,一个画布里 1000 个图形各自的位置状态更新时,只有真正依赖了对应原子的组件才会重渲染。用 Redux 做同样的事,你需要非常小心地使用 reselect 做 memoized selector,或者通过 shallowEqual 避免不必要的重渲染,但本质上 Redux 的 useSelector 是从一个大的 state tree 里取值,selector 的粒度控制全在开发者手里,出问题的概率更高。
另一个性能敏感场景是 bundle size。如果你的产品是嵌入到第三方网站的 SDK 或 Widget,每个 kB 都很重要。Zustand v5 的 1.1kB 对比 Redux Toolkit 的大约 11kB(gzipped),在这个场景下是有意义的差距。但对于常规 Web 应用,11kB 基本可以忽略不计。
需要特别提一下 React 19 和 React Compiler。React 19 在 2024 年 12 月正式发布,React Compiler(以前的 React Forget)也开始在 Instagram 等 Meta 内部应用中大规模使用。Compiler 的自动 memoization 会大幅减少手动 useMemo/useCallback 的需求,这间接降低了 Redux selector 优化的重要性。当编译器能自动判断依赖变化时,以前那些因为没加 shallowEqual 导致的重渲染问题会减少。但 Compiler 不改变状态管理库本身的订阅机制,所以原子型方案在极端高频场景下的粒度优势仍然存在。
决策框架实操:三问定方案
把三个维度串起来,我平时做选型决策时问自己三个问题:
第一问:你的状态是「服务端镜像」为主,还是「客户端模型」为主?
如果 80% 以上的状态都是从 API 拉回来、缓存、展示,那优先用 React Query(或 SWR)+ 轻量客户端状态(Context 或 Zustand)。不要在这个阶段引入 Redux,否则你会发现大部分 Redux 代码都在做 data fetching,而 React Query 已经把这件事做得更好了。
如果核心状态是客户端自己产生的——比如一个设计工具的图层树、一个游戏的实体状态——那需要真正的状态管理库。进入第二问。
第二问:状态之间的依赖复杂吗?更新粒度需要多细?
如果状态之间互相独立、或者依赖关系简单(比如购物车只依赖商品列表和用户 ID),Zustand 足够。3-5 个 slice,每个 slice 独立,没有跨 slice 的复杂交互。
如果状态之间有大量交叉依赖,一个操作需要同时更新多个不相关的状态切片(比如「撤销」操作需要回滚画布、属性面板、历史记录三层状态),Redux 的单一 Store 和中间件模型更适合。或者如果你需要细粒度更新——一个列表里某个 item 的状态变更不触发整个列表重渲染——Jotai 更合适。
第三问:团队有多大?人员流动率如何?
小团队(3-5 人)、人员稳定:选学习成本最低的,Zustand 或 Jotai,快速迭代。
大团队(10 人以上)、有人员流动:Redux 的约束性是一笔长期资产。代码写得不那么优雅的时候,至少状态变更的路径是可追踪的,DevTools 能看到每一步 action,新人接手时的认知负荷反而比看一堆自由发挥的 Zustand slice 要低。
常见问题
我现在的项目已经用 Redux 了,要迁到 Zustand 或 Jotai 吗?
大多数情况下不需要,除非你正在经历明显的开发效率问题。迁移状态管理库的成本极高——不是 API 替换的工作量,而是整个团队的心智模型切换和回归测试。如果你的 Redux 代码是用 RTK 写的、没有严重的性能瓶颈,继续用就行。一个更务实的策略是:新功能模块用 Zustand 或 Jotai 写,老模块不动,渐进式替换。Redux 和 Zustand 可以在同一个项目里共存,互不冲突。
React 19 和 Server Components 会让状态管理库变得不重要吗?
会削减需求,但不会消灭。Server Components 把大量「从服务端取数据、渲染、展示」的逻辑移到了服务端,这部分场景确实不再需要客户端状态管理。但任何有交互的客户端状态——表单、弹窗、实时协作、离线编辑——仍然需要状态管理。变化在于,以前很多人用 Redux 管理的数据里,可能有 60% 其实是服务端数据的客户端缓存,这部分会被 React Query 或 Server Components 替代;剩下 40% 真正的客户端状态,仍然需要一个库来管。
Zustand 和 Jotai 怎么选?它们看起来很像。
Zustand 是「一个大的 Store,内部可以按 slice 拆分」,适合状态之间有自然聚集关系的场景。Jotai 是「一堆独立的原子,按需组合」,适合状态天然分散、需要细粒度订阅的场景。举个例子:一个用户设置页面,里面有十几个独立的开关和输入框,它们之间几乎没有联动——用 Jotai 很自然,每个开关一个 atom。一个电商购物车,商品列表、优惠券、配送地址之间有强联动——用 Zustand 更直观,一个 cart slice 搞定。两个库的作者是同一个人(Daishi Kato),设计哲学上有延续性,选哪个更多是看你的状态结构长什么样。