news 2026/5/24 14:50:19

React 从入门到生产(五):状态管理选型

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
React 从入门到生产(五):状态管理选型

创作者:Yardon |GitHub:github.com/YardonYan |版本:v1.0



什么时候需要状态管理

先泼一盆冷水:大多数 React 应用不需要 Redux。

这句话不是我说的,是 Redux 的作者 Dan Abramov 本人说的。他在 2020 年就公开表示,在他参与的大多数项目中,Redux 已经不再是最好的选择。

那么什么时候真的需要「状态管理库」?

当你的应用满足以下任意一个条件时:

  • 超过 3 层嵌套的组件需要共享同一个状态
  • 多个不相关的页面需要访问同一份数据
  • 状态变更的逻辑非常复杂(多个 action 之间有依赖关系)
  • 需要时间旅行调试(undo/redo)

其他情况?useState+useContext足够了。


React 自带的方案回顾

在介绍第三方库之前,先把 React 自带的工具说清楚。

Props Drilling(属性穿透)

最基础的方式就是通过 props 一层层往下传:

App → Header → NavBar → Logo ↓ UserMenu → Avatar → Dropdown → Item

如果 UserMenu 和 NavBar 都需要访问currentUser,而currentUser定义在 App 组件里——你得把它一层层往下传。这在浅层嵌套时没问题,但如果你的组件树有 5-6 层深,每层都要"过手"一个跟它们毫无关系的 props,这就成了「属性穿透地狱」。

想象你在一栋公寓里,每层都住着互不相识的邻居,但暖气管道要穿过每一家的客厅。物业公司的员工(中间组件)被迫了解每家每户的暖气情况——尽管他只需要把暖气送到就行了。

Context API:内置的跨组件通信

Context就是来解决这个问题的——让你在组件树的任意位置访问数据,而不需要手动层层传递。


Context API:轻量级全局状态

基本用法

// ThemeContext.jsx import { createContext, useContext, useState } from 'react'; const ThemeContext = createContext(); export function ThemeProvider({ children }) { const [theme, setTheme] = useState('dark'); function toggleTheme() { setTheme(t => t === 'dark' ? 'light' : 'dark'); } return ( <ThemeContext.Provider value={{ theme, toggleTheme }}> {children} </ThemeContext.Provider> ); } export function useTheme() { const context = useContext(ThemeContext); if (!context) throw new Error('useTheme 必须在 ThemeProvider 内使用'); return context; }
// App.jsx import { ThemeProvider } from './ThemeContext'; function App() { return ( <ThemeProvider> <Dashboard /> </ThemeProvider> ); } // 任意子组件中 function SettingsPage() { const { theme, toggleTheme } = useTheme(); return <button onClick={toggleTheme}>当前: {theme}</button>; }

Context 的性能陷阱

Context 最大的坑在于:Provider 下的所有组件都会在 Context 值变化时重新渲染。

// ❌ 每秒更新一次,所有消费者都 re-render function App() { const [time, setTime] = useState(Date.now()); useEffect(() => { const id = setInterval(() => setTime(Date.now()), 1000); return () => clearInterval(id); }, []); return <ThemeContext.Provider value={{ time }}>...</ThemeContext.Provider>; } // ✅ 只暴露必要的状态 function App() { const [time, setTime] = useState(Date.now()); const { theme } = useThemeContext(); // 只订阅需要的 useEffect(() => { const id = setInterval(() => setTime(Date.now()), 1000); return () => clearInterval(id); }, []); return <ThemeContext.Provider value={{ theme, time }}>...</ThemeContext.Provider>; }

最佳实践:按功能拆分成多个独立的 Context。

// 主题一个 Context,用户信息一个 Context,购物车一个 Context // 每个 Context 只订阅它真正需要的数据 <ThemeContext.Provider value={theme}> <UserContext.Provider value={user}> <CartContext.Provider value={cart}> <App /> </CartContext.Provider> </UserContext.Provider> </ThemeContext.Provider>

这样只有购物车变了,Header 里的主题切换按钮才不会无辜地重新渲染。


Zustand:极简主义的代表

Zustand 是 2020 年后最火的状态管理库。它用起来非常简单——5 分钟就能上手。

核心概念

// store/useCartStore.js import { create } from &#039;zustand&#039;; const useCartStore = create((set, get) =&gt; ({ items: [], total: 0, addItem: (product) =&gt; set((state) =&gt; ({ items: [...state.items, product], total: state.total + product.price, })), removeItem: (id) =&gt; set((state) =&gt; { const item = state.items.find(i =&gt; i.id === id); return { items: state.items.filter(i =&gt; i.id !== id), total: state.total - (item?.price || 0), }; }), clearCart: () =&gt; set({ items: [], total: 0 }), // 直接读取 state,不需要 hooks getItemCount: () =&gt; get().items.length, }));
// 在组件中使用 function CartIcon() { const itemCount = useCartStore(s =&gt; s.items.length); return &lt;span&gt;🛒 {itemCount}&lt;/span&gt;; } function CartPage() { const { items, total, removeItem, clearCart } = useCartStore(); return ( &lt;div&gt; {items.map(item =&gt; &lt;CartItem key={item.id} item={item} onRemove={removeItem} /&gt;)} &lt;p&gt;总计: ¥{total}&lt;/p&gt; &lt;button onClick={clearCart}&gt;清空购物车&lt;/button&gt; &lt;/div&gt; ); }

为什么选择 Zustand

特性ZustandRedux Toolkit
代码量极简(~50行一个store)需要 action/reducer/store boilerplate
学习曲线几乎为零中等(概念多)
DevTools支持强大(时间旅行等)
适用场景中小型应用大型复杂应用
包大小~1KB~15KB

Redux Toolkit:复杂应用的选择

Redux 曾经是 React 状态管理的代名词。2019 年 Redux Toolkit 的出现大幅降低了使用门槛,但它的复杂性依然高于 Zustand。

核心概念:Slice

// features/cart/cartSlice.jsimport{createSlice}from&#039;@reduxjs/toolkit&#039;;constcartSlice=createSlice({name:&#039;cart&#039;,initialState:{items:[],total:0},reducers:{addItem:(state,action)=&gt;{state.items.push(action.payload);state.total+=action.payload.price;},removeItem:(state,action)=&gt;{constidx=state.items.findIndex(i=&gt;i.id===action.payload);if(idx!==-1){state.total-=state.items[idx].price;state.items.splice(idx,1);}},clearCart:(state)=&gt;{state.items=[];state.total=0;},},});exportconst{addItem,removeItem,clearCart}=cartSlice.actions;exportdefaultcartSlice.reducer;
// store/index.jsimport{configureStore}from&#039;@reduxjs/toolkit&#039;;importcartReducer from&#039;./features/cart/cartSlice&#039;;exportconststore=configureStore({reducer:{cart:cartReducer,user:userReducer,// ...},});
// 组件中使用 import { useSelector, useDispatch } from &#039;react-redux&#039;; import { addItem } from &#039;./features/cart/cartSlice&#039;; function ProductPage({ product }) { const dispatch = useDispatch(); const isInCart = useSelector(s =&gt; s.cart.items.some(i =&gt; i.id === product.id) ); return ( &lt;div&gt; &lt;h1&gt;{product.name}&lt;/h1&gt; &lt;button disabled={isInCart} onClick={() =&gt; dispatch(addItem(product))} &gt; {isInCart ? &#039;已在购物车&#039; : &#039;加入购物车&#039;} &lt;/button&gt; &lt;/div&gt; ); }

Redux Toolkit 适合什么时候?当你有多个开发者协作的大型项目,需要严格的状态流转规范、时间旅行调试、批量操作日志时,Redux 的约束反而是优点——它强制你用规范的方式做事,不容易出现"状态不知道从哪改的"的情况。


Jotai:原子化状态管理

Jotai 是一个相对小众但很有特色的方案。它的核心概念是原子(Atom)——最小的状态单元。

// atoms.js import { atom } from &#039;jotai&#039;; // 基础原子 const userAtom = atom(null); const notificationCountAtom = atom(0); // 派生原子(类似 useMemo) const hasNotificationsAtom = atom(get =&gt; get(notificationCountAtom) &gt; 0); // 写原子 const addNotificationAtom = atom( null, (get, set) =&gt; { const current = get(notificationCountAtom); set(notificationCountAtom, current + 1); } );
// 组件中只订阅需要的原子 function NotificationBadge() { const count = useAtom(notificationCountAtom)[0]; return count &gt; 0 ? &lt;span&gt;{count}&lt;/span&gt; : null; } function NotificationButton() { const [, addNotification] = useAtom(addNotificationAtom); return &lt;button onClick={addNotification}&gt;有新消息&lt;/button&gt;; }

Jotai 的优势是细粒度更新——只有真正用到某个原子值的组件才会重新渲染。它适合状态很多、更新很频繁的应用(比如实时协作工具、数据可视化面板)。


选型决策树

应用规模? ├── 小型(几个页面,状态简单) │ └── useState + Context API ✅ 够了 │ ├── 中型(10+ 页面,多人协作) │ ├── 状态种类多、更新频繁 │ │ └── Zustand ✅ 推荐 │ │ │ └── 需要强规范、强调试能力 │ └── Redux Toolkit ✅ │ └── 大型(复杂状态流转、undo/redo) └── Redux Toolkit ✅ 或 Recoil

我的推荐(2026 年):

  • 90% 的项目:useState+ContextZustand
  • 5% 的项目需要强规范:Redux Toolkit
  • 5% 的项目状态极细:Jotai

本章小结

工具适用场景代码量学习成本
useState + Context小型应用、简单全局状态
Context API(多 Context)中型应用、分域全局状态
Zustand中小型应用、需要灵活状态极少极低
Redux Toolkit大型、复杂、多人协作
Jotai细粒度状态、频繁更新

状态管理的本质是数据的流向和共享。选什么工具不重要,重要的是理解为什么需要它、它解决的是什么问题。下一章我们聊聊React Router——单页应用如何实现页面跳转和 URL 管理。


📌创作者:Yardon | 🏠个人网站:GlimmerAI.top

📖 本章是「React 从入门到生产」系列的第 5 章。上一章:自定义Hook | 下一章:路由与导航

🌟 如果你觉得有帮助,欢迎访问 GlimmerAI.top 查看我的更多作品。欢迎大家来观看!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/22 19:58:27

为什么Outfit字体是现代设计系统的几何美学革命

为什么Outfit字体是现代设计系统的几何美学革命 【免费下载链接】Outfit-Fonts The most on-brand typeface 项目地址: https://gitcode.com/gh_mirrors/ou/Outfit-Fonts 深夜的设计工作室里&#xff0c;咖啡已经凉透&#xff0c;屏幕上的品牌方案却始终差那么一点"…

作者头像 李华
网站建设 2026/5/22 19:53:04

2026年京东云OpenClaw/Hermes Agent配置Token Plan集成操作全流程

2026年京东云OpenClaw/Hermes Agent配置Token Plan集成操作全流程。OpenClaw是开源的个人AI助手&#xff0c;Hermes Agent则是一个能自我进化的AI智能体框架。阿里云提供计算巢、轻量服务器及无影云电脑三种部署OpenClaw 与 Hermes Agent的方案、百炼Token Plan兼容主流 AI 工具…

作者头像 李华
网站建设 2026/5/22 19:49:38

Taotoken 多模型聚合能力如何赋能智能客服场景的快速迭代

&#x1f680; 告别海外账号与网络限制&#xff01;稳定直连全球优质大模型&#xff0c;限时半价接入中。 &#x1f449; 点击领取海量免费额度 Taotoken 多模型聚合能力如何赋能智能客服场景的快速迭代 智能客服系统的核心在于其对话生成的质量与稳定性。产品经理与开发者在优…

作者头像 李华
网站建设 2026/5/22 19:45:08

告别视频孤岛:3分钟让B站缓存视频重获新生 [特殊字符]

告别视频孤岛&#xff1a;3分钟让B站缓存视频重获新生 &#x1f31f; 【免费下载链接】m4s-converter 一个跨平台小工具&#xff0c;将bilibili缓存的m4s格式音视频文件合并成mp4 项目地址: https://gitcode.com/gh_mirrors/m4/m4s-converter 你是否曾经为心爱的B站视频…

作者头像 李华
网站建设 2026/5/22 19:39:26

嵌入式安全开发实践:从威胁建模到安全左移的全流程指南

1. 项目概述&#xff1a;为什么安全开发不再是“可选项”&#xff1f;干了十几年嵌入式软件开发&#xff0c;从早期的单片机裸跑到现在的复杂多核异构系统&#xff0c;我最大的感触就是&#xff1a;安全这件事&#xff0c;以前是“锦上添花”&#xff0c;现在是“生死攸关”。项…

作者头像 李华