前言:一种名为“Redux 肌肉记忆”的病
如果你是一个入行超过 5 年的前端,你一定有过这种经历:
新起一个项目,create-react-app (或者 Vite) 刚跑完,还没写第一行业务代码,你就习惯性地开始安装 redux、react-redux、redux-thunk(或者是现在的 zustand)。
然后熟练地创建 store 文件夹,写 actions,写 reducers,写 types。
停!打住!
你要做的可能只是一个“获取用户列表”的功能。
为了这一行数据,你写了 5 个文件,搞了一套复杂的“单向数据流”。
兄弟,承认吧,你不是在写代码,你是在搞装修。你把一个 30 平米的出租屋(简单的 CRUD 页面),装修成了卢浮宫。
今天,我要当那个拆迁办主任,带你把这些不必要的“脚手架”全拆了。
真相一:你眼中的“全局状态”,其实大部分是“服务端缓存”
很多初学者(甚至资深开发)最大的误区,就是把API 数据当成了全局状态。
仔细看看你的 Redux Store,里面存的是什么?
userList: 后端返的。productDetails: 后端返的。isLoading: 用来判断是不是在请求后端的。error: 请求后端失败拿到的。
醒醒!这不叫 State(状态),这叫 Server Cache(服务端数据缓存)。
你把后端的数据搬运到 Redux 里,你是舒服了,但你给自己找了一堆麻烦:
- 同步地狱:后端数据变了,你得手动 dispatch action 去更新 store。
- 过期处理:用户切出页面再回来,数据要不要刷新?你得自己写逻辑。
- 重复请求:两个组件同时需要这数据,怎么防抖?你还得写逻辑。
这就是为什么你需要 React Query (或者 SWR)。
看看对比(这是降维打击):
🔴 Redux/Zustand 传统流派:
- 定义
FETCH_USER_START,FETCH_USER_SUCCESS,FETCH_USER_FAIL。 - 写一个 Thunk/Saga 中间件处理异步。
- 在组件里
useEffect触发 dispatch。 - 用
useSelector拿数据,还要处理 loading 状态。
🟢 React Query 流派:
const { data, isLoading, error } = useQuery(['user', id], () => fetchUser(id));
完了。 没错,就这一行。
它自带了:缓存、自动重试、窗口聚焦自动刷新、数据去重。 你原本那 200 行 Redux 模板代码,现在只需要这一行 hook。
真相二:剩下的 UI 状态,Context 绰绰有余
“那把 API 数据拿走了,我剩下的状态放哪?”
我们看看剩下的通常是什么:
- 主题色(Light/Dark Mode)
- 当前登录用户信息
- 侧边栏展开/收起
- 多语言设置
发现没有?这些状态有两个特点:
- 低频更新(你不会一秒钟切换 10 次主题色)。
- 真正的全局(整个 App 都在用)。
对于这种场景,React 自带的 Context + useReducer (或者 useState) 是完美的解决方案。
别信那些“Context 性能很差”的鬼话。 只要你按照我前几篇文章写的,合理拆分 Context(把 UserContext 和 ThemeContext 分开),性能完全不是瓶颈。
为了存一个 isSidebarOpen 布尔值,去引入一个几十 KB 的 Redux 库,就像是为了切蒜瓣专门买了一台工业级切割机。
灵魂拷问:什么时候你真的需要 Zustand/Redux?
我不是说这些库一无是处。Zustand 很棒,Redux Toolkit 也很强。 但它们是为了复杂客户端状态而生的。
请问你的项目里有以下场景吗?
- 图形编辑器:像 Figma、Photoshop 网页版那样,有大量的图形对象、图层、撤销/重做栈。
- 复杂的表单向导:Step 1 的选择会极其复杂地影响 Step 5 的选项,且中间有非线性的跳转逻辑。
- 高频实时数据:股票 K 线图、即时对战游戏,数据一秒钟变 60 次,直接用 Context 确实会卡。
如果你的答案是 “No,我只是在写一个后台管理系统 / 电商首页 / 个人博客” 。
那么恭喜你,React Query 处理 API 数据 + Context 处理 UI 状态,就是你的终极答案。
总结:少写代码,多享受生活
架构设计的最高境界,不是你用了多少牛逼的库,而是你少写了多少代码也能达到同样的效果。
自从我把项目从 Redux 迁移到 React Query 后:
- 代码量减少了 40%。
- Bug(尤其是数据同步类的)减少了 80%。
- 同事看我的代码再也不骂娘了。
下次再有人让你“先建个 Store”,请直接把这篇文章甩他脸上,然后用省下来的时间去喝杯咖啡。
下期预告:你是不是特别讨厌“Props Drilling”(属性透传),为了避免它才用的 Redux? 其实,只要你懂**“组件组合(Component Composition)”**,也就是神奇的
children属性,你会发现 Props Drilling 根本就是个伪命题。 下一篇,教你如何像乐高大师一样拼装组件。

被折叠的 条评论
为什么被折叠?



