前端状态管理比较选择适合你的状态管理方案毒舌时刻状态管理听起来就像是前端工程师为了显得自己很高级而特意发明的复杂概念。你以为随便找个状态管理库就能解决所有问题别做梦了到时候你会发现状态管理库本身就是个问题。你以为Redux是万能的别天真了Redux的样板代码多到让你崩溃调试起来也非常麻烦。还有那些所谓的轻量级状态管理库看起来简单用起来却各种问题。为什么你需要这个复杂状态管理当应用变得复杂时组件间的状态共享和管理会变得非常困难需要一个专门的状态管理方案。可预测性良好的状态管理方案可以让状态变化变得可预测便于调试和测试。性能优化状态管理方案可以帮助你优化组件渲染提高应用性能。代码组织状态管理方案可以帮助你更好地组织代码提高代码的可维护性。团队协作统一的状态管理方案可以便于团队成员之间的协作减少沟通成本。反面教材// 这是一个典型的状态管理混乱的例子 import React, { useState, useEffect } from react; function App() { const [user, setUser] useState(null); const [products, setProducts] useState([]); const [cart, setCart] useState([]); const [loading, setLoading] useState(false); const [error, setError] useState(null); // 获取用户信息 useEffect(() { async function fetchUser() { setLoading(true); try { const response await fetch(/api/user); const data await response.json(); setUser(data); } catch (err) { setError(Failed to fetch user); } finally { setLoading(false); } } fetchUser(); }, []); // 获取产品列表 useEffect(() { async function fetchProducts() { setLoading(true); try { const response await fetch(/api/products); const data await response.json(); setProducts(data); } catch (err) { setError(Failed to fetch products); } finally { setLoading(false); } } fetchProducts(); }, []); // 添加到购物车 const addToCart (product) { setCart(prevCart [...prevCart, product]); }; // 从购物车移除 const removeFromCart (productId) { setCart(prevCart prevCart.filter(item item.id ! productId)); }; return ( div {loading divLoading.../div} {error div{error}/div} {user divWelcome, {user.name}!/div} h2Products/h2 div classNameproducts {products.map(product ( div key{product.id} classNameproduct h3{product.name}/h3 p{product.price}/p button onClick{() addToCart(product)}Add to Cart/button /div ))} /div h2Cart/h2 div classNamecart {cart.map(item ( div key{item.id} classNamecart-item h4{item.name}/h4 p{item.price}/p button onClick{() removeFromCart(item.id)}Remove/button /div ))} /div /div ); } export default App;问题状态分散在各个组件中难以管理组件间的状态共享需要通过props传递层次深时会产生props drilling状态变化不可预测难以调试性能优化困难状态更新时可能导致不必要的重渲染代码组织混乱难以维护正确的做法React Context useReducer// store.js import React, { createContext, useContext, useReducer } from react; // 初始状态 const initialState { user: null, products: [], cart: [], loading: false, error: null }; // Action类型 const ActionTypes { SET_USER: SET_USER, SET_PRODUCTS: SET_PRODUCTS, ADD_TO_CART: ADD_TO_CART, REMOVE_FROM_CART: REMOVE_FROM_CART, SET_LOADING: SET_LOADING, SET_ERROR: SET_ERROR }; // Reducer function reducer(state, action) { switch (action.type) { case ActionTypes.SET_USER: return { ...state, user: action.payload }; case ActionTypes.SET_PRODUCTS: return { ...state, products: action.payload }; case ActionTypes.ADD_TO_CART: return { ...state, cart: [...state.cart, action.payload] }; case ActionTypes.REMOVE_FROM_CART: return { ...state, cart: state.cart.filter(item item.id ! action.payload) }; case ActionTypes.SET_LOADING: return { ...state, loading: action.payload }; case ActionTypes.SET_ERROR: return { ...state, error: action.payload }; default: return state; } } // 创建Context const StoreContext createContext(); // Provider组件 export function StoreProvider({ children }) { const [state, dispatch] useReducer(reducer, initialState); return ( StoreContext.Provider value{{ state, dispatch }} {children} /StoreContext.Provider ); } // 自定义Hook export function useStore() { const context useContext(StoreContext); if (!context) { throw new Error(useStore must be used within a StoreProvider); } return context; } // Action creators export const actions { setUser: (user) ({ type: ActionTypes.SET_USER, payload: user }), setProducts: (products) ({ type: ActionTypes.SET_PRODUCTS, payload: products }), addToCart: (product) ({ type: ActionTypes.ADD_TO_CART, payload: product }), removeFromCart: (productId) ({ type: ActionTypes.REMOVE_FROM_CART, payload: productId }), setLoading: (loading) ({ type: ActionTypes.SET_LOADING, payload: loading }), setError: (error) ({ type: ActionTypes.SET_ERROR, payload: error }) }; // App.js import React, { useEffect } from react; import { StoreProvider, useStore, actions } from ./store; function AppContent() { const { state, dispatch } useStore(); const { user, products, cart, loading, error } state; // 获取用户信息 useEffect(() { async function fetchUser() { dispatch(actions.setLoading(true)); try { const response await fetch(/api/user); const data await response.json(); dispatch(actions.setUser(data)); } catch (err) { dispatch(actions.setError(Failed to fetch user)); } finally { dispatch(actions.setLoading(false)); } } fetchUser(); }, []); // 获取产品列表 useEffect(() { async function fetchProducts() { dispatch(actions.setLoading(true)); try { const response await fetch(/api/products); const data await response.json(); dispatch(actions.setProducts(data)); } catch (err) { dispatch(actions.setError(Failed to fetch products)); } finally { dispatch(actions.setLoading(false)); } } fetchProducts(); }, []); return ( div {loading divLoading.../div} {error div{error}/div} {user divWelcome, {user.name}!/div} h2Products/h2 div classNameproducts {products.map(product ( div key{product.id} classNameproduct h3{product.name}/h3 p{product.price}/p button onClick{() dispatch(actions.addToCart(product))} Add to Cart /button /div ))} /div h2Cart/h2 div classNamecart {cart.map(item ( div key{item.id} classNamecart-item h4{item.name}/h4 p{item.price}/p button onClick{() dispatch(actions.removeFromCart(item.id))} Remove /button /div ))} /div /div ); } function App() { return ( StoreProvider AppContent / /StoreProvider ); } export default App;Redux// store.js import { configureStore, createSlice } from reduxjs/toolkit; // 用户Slice const userSlice createSlice({ name: user, initialState: null, reducers: { setUser: (state, action) action.payload } }); // 产品Slice const productsSlice createSlice({ name: products, initialState: [], reducers: { setProducts: (state, action) action.payload } }); // 购物车Slice const cartSlice createSlice({ name: cart, initialState: [], reducers: { addToCart: (state, action) [...state, action.payload], removeFromCart: (state, action) state.filter(item item.id ! action.payload) } }); // 加载状态Slice const loadingSlice createSlice({ name: loading, initialState: false, reducers: { setLoading: (state, action) action.payload } }); // 错误状态Slice const errorSlice createSlice({ name: error, initialState: null, reducers: { setError: (state, action) action.payload } }); // 导出actions export const { setUser } userSlice.actions; export const { setProducts } productsSlice.actions; export const { addToCart, removeFromCart } cartSlice.actions; export const { setLoading } loadingSlice.actions; export const { setError } errorSlice.actions; // 配置store const store configureStore({ reducer: { user: userSlice.reducer, products: productsSlice.reducer, cart: cartSlice.reducer, loading: loadingSlice.reducer, error: errorSlice.reducer } }); export default store; // App.js import React, { useEffect } from react; import { Provider, useDispatch, useSelector } from react-redux; import store, { setUser, setProducts, addToCart, removeFromCart, setLoading, setError } from ./store; function AppContent() { const dispatch useDispatch(); const user useSelector(state state.user); const products useSelector(state state.products); const cart useSelector(state state.cart); const loading useSelector(state state.loading); const error useSelector(state state.error); // 获取用户信息 useEffect(() { async function fetchUser() { dispatch(setLoading(true)); try { const response await fetch(/api/user); const data await response.json(); dispatch(setUser(data)); } catch (err) { dispatch(setError(Failed to fetch user)); } finally { dispatch(setLoading(false)); } } fetchUser(); }, [dispatch]); // 获取产品列表 useEffect(() { async function fetchProducts() { dispatch(setLoading(true)); try { const response await fetch(/api/products); const data await response.json(); dispatch(setProducts(data)); } catch (err) { dispatch(setError(Failed to fetch products)); } finally { dispatch(setLoading(false)); } } fetchProducts(); }, [dispatch]); return ( div {loading divLoading.../div} {error div{error}/div} {user divWelcome, {user.name}!/div} h2Products/h2 div classNameproducts {products.map(product ( div key{product.id} classNameproduct h3{product.name}/h3 p{product.price}/p button onClick{() dispatch(addToCart(product))} Add to Cart /button /div ))} /div h2Cart/h2 div classNamecart {cart.map(item ( div key{item.id} classNamecart-item h4{item.name}/h4 p{item.price}/p button onClick{() dispatch(removeFromCart(item.id))} Remove /button /div ))} /div /div ); } function App() { return ( Provider store{store} AppContent / /Provider ); } export default App;MobX// store.js import { makeAutoObservable } from mobx; class Store { user null; products []; cart []; loading false; error null; constructor() { makeAutoObservable(this); } // Actions setUser(user) { this.user user; } setProducts(products) { this.products products; } addToCart(product) { this.cart.push(product); } removeFromCart(productId) { this.cart this.cart.filter(item item.id ! productId); } setLoading(loading) { this.loading loading; } setError(error) { this.error error; } // Async actions async fetchUser() { this.setLoading(true); try { const response await fetch(/api/user); const data await response.json(); this.setUser(data); } catch (err) { this.setError(Failed to fetch user); } finally { this.setLoading(false); } } async fetchProducts() { this.setLoading(true); try { const response await fetch(/api/products); const data await response.json(); this.setProducts(data); } catch (err) { this.setError(Failed to fetch products); } finally { this.setLoading(false); } } } // 导出单例 export const store new Store(); // App.js import React, { useEffect } from react; import { observer } from mobx-react-lite; import { store } from ./store; const AppContent observer(() { const { user, products, cart, loading, error } store; // 获取用户信息 useEffect(() { store.fetchUser(); }, []); // 获取产品列表 useEffect(() { store.fetchProducts(); }, []); return ( div {loading divLoading.../div} {error div{error}/div} {user divWelcome, {user.name}!/div} h2Products/h2 div classNameproducts {products.map(product ( div key{product.id} classNameproduct h3{product.name}/h3 p{product.price}/p button onClick{() store.addToCart(product)} Add to Cart /button /div ))} /div h2Cart/h2 div classNamecart {cart.map(item ( div key{item.id} classNamecart-item h4{item.name}/h4 p{item.price}/p button onClick{() store.removeFromCart(item.id)} Remove /button /div ))} /div /div ); }); function App() { return AppContent /; } export default App;Recoil// store.js import { atom, selector } from recoil; // Atoms export const userAtom atom({ key: user, default: null }); export const productsAtom atom({ key: products, default: [] }); export const cartAtom atom({ key: cart, default: [] }); export const loadingAtom atom({ key: loading, default: false }); export const errorAtom atom({ key: error, default: null }); // Selectors export const cartTotalSelector selector({ key: cartTotal, get: ({ get }) { const cart get(cartAtom); return cart.reduce((total, item) total item.price, 0); } }); // App.js import React, { useEffect } from react; import { RecoilRoot, useRecoilState, useRecoilValue } from recoil; import { userAtom, productsAtom, cartAtom, loadingAtom, errorAtom, cartTotalSelector } from ./store; function AppContent() { const [user, setUser] useRecoilState(userAtom); const [products, setProducts] useRecoilState(productsAtom); const [cart, setCart] useRecoilState(cartAtom); const [loading, setLoading] useRecoilState(loadingAtom); const [error, setError] useRecoilState(errorAtom); const cartTotal useRecoilValue(cartTotalSelector); // 获取用户信息 useEffect(() { async function fetchUser() { setLoading(true); try { const response await fetch(/api/user); const data await response.json(); setUser(data); } catch (err) { setError(Failed to fetch user); } finally { setLoading(false); } } fetchUser(); }, [setUser, setLoading, setError]); // 获取产品列表 useEffect(() { async function fetchProducts() { setLoading(true); try { const response await fetch(/api/products); const data await response.json(); setProducts(data); } catch (err) { setError(Failed to fetch products); } finally { setLoading(false); } } fetchProducts(); }, [setProducts, setLoading, setError]); const addToCart (product) { setCart(prevCart [...prevCart, product]); }; const removeFromCart (productId) { setCart(prevCart prevCart.filter(item item.id ! productId)); }; return ( div {loading divLoading.../div} {error div{error}/div} {user divWelcome, {user.name}!/div} h2Products/h2 div classNameproducts {products.map(product ( div key{product.id} classNameproduct h3{product.name}/h3 p{product.price}/p button onClick{() addToCart(product)} Add to Cart /button /div ))} /div h2Cart/h2 div classNamecart {cart.map(item ( div key{item.id} classNamecart-item h4{item.name}/h4 p{item.price}/p button onClick{() removeFromCart(item.id)} Remove /button /div ))} div classNamecart-total h3Total: {cartTotal}/h3 /div /div /div ); } function App() { return ( RecoilRoot AppContent / /RecoilRoot ); } export default App;Zustand// store.js import create from zustand; const useStore create((set) ({ // State user: null, products: [], cart: [], loading: false, error: null, // Actions setUser: (user) set({ user }), setProducts: (products) set({ products }), addToCart: (product) set((state) ({ cart: [...state.cart, product] })), removeFromCart: (productId) set((state) ({ cart: state.cart.filter(item item.id ! productId) })), setLoading: (loading) set({ loading }), setError: (error) set({ error }), // Async actions fetchUser: async () { set({ loading: true, error: null }); try { const response await fetch(/api/user); const data await response.json(); set({ user: data, loading: false }); } catch (err) { set({ error: Failed to fetch user, loading: false }); } }, fetchProducts: async () { set({ loading: true, error: null }); try { const response await fetch(/api/products); const data await response.json(); set({ products: data, loading: false }); } catch (err) { set({ error: Failed to fetch products, loading: false }); } } })); export default useStore; // App.js import React, { useEffect } from react; import useStore from ./store; function App() { const { user, products, cart, loading, error, setUser, setProducts, addToCart, removeFromCart, setLoading, setError, fetchUser, fetchProducts } useStore(); // 获取用户信息 useEffect(() { fetchUser(); }, [fetchUser]); // 获取产品列表 useEffect(() { fetchProducts(); }, [fetchProducts]); return ( div {loading divLoading.../div} {error div{error}/div} {user divWelcome, {user.name}!/div} h2Products/h2 div classNameproducts {products.map(product ( div key{product.id} classNameproduct h3{product.name}/h3 p{product.price}/p button onClick{() addToCart(product)} Add to Cart /button /div ))} /div h2Cart/h2 div classNamecart {cart.map(item ( div key{item.id} classNamecart-item h4{item.name}/h4 p{item.price}/p button onClick{() removeFromCart(item.id)} Remove /button /div ))} /div /div ); } export default App;Jotai// store.js import { atom } from jotai; // Atoms export const userAtom atom(null); export const productsAtom atom([]); export const cartAtom atom( (get) get(_cartAtom), (get, set, product) set(_cartAtom, [...get(_cartAtom), product]) ); const _cartAtom atom([]); export const removeFromCartAtom atom( null, (get, set, productId) set(_cartAtom, get(_cartAtom).filter(item item.id ! productId)) ); export const loadingAtom atom(false); export const errorAtom atom(null); export const cartTotalAtom atom( (get) get(_cartAtom).reduce((total, item) total item.price, 0) ); // App.js import React, { useEffect } from react; import { useAtom } from jotai; import { userAtom, productsAtom, cartAtom, removeFromCartAtom, loadingAtom, errorAtom, cartTotalAtom } from ./store; function App() { const [user, setUser] useAtom(userAtom); const [products, setProducts] useAtom(productsAtom); const [cart, addToCart] useAtom(cartAtom); const [, removeFromCart] useAtom(removeFromCartAtom); const [loading, setLoading] useAtom(loadingAtom); const [error, setError] useAtom(errorAtom); const [cartTotal] useAtom(cartTotalAtom); // 获取用户信息 useEffect(() { async function fetchUser() { setLoading(true); try { const response await fetch(/api/user); const data await response.json(); setUser(data); } catch (err) { setError(Failed to fetch user); } finally { setLoading(false); } } fetchUser(); }, [setUser, setLoading, setError]); // 获取产品列表 useEffect(() { async function fetchProducts() { setLoading(true); try { const response await fetch(/api/products); const data await response.json(); setProducts(data); } catch (err) { setError(Failed to fetch products); } finally { setLoading(false); } } fetchProducts(); }, [setProducts, setLoading, setError]); return ( div {loading divLoading.../div} {error div{error}/div} {user divWelcome, {user.name}!/div} h2Products/h2 div classNameproducts {products.map(product ( div key{product.id} classNameproduct h3{product.name}/h3 p{product.price}/p button onClick{() addToCart(product)} Add to Cart /button /div ))} /div h2Cart/h2 div classNamecart {cart.map(item ( div key{item.id} classNamecart-item h4{item.name}/h4 p{item.price}/p button onClick{() removeFromCart(item.id)} Remove /button /div ))} div classNamecart-total h3Total: {cartTotal}/h3 /div /div /div ); } export default App;毒舌点评状态管理确实很重要但我见过太多开发者滥用状态管理库导致应用变得更加复杂。想象一下当你为了一个简单的应用引入Redux结果写了大量的样板代码这真的值得吗还有那些过度使用状态管理的开发者把所有状态都放在全局状态中结果导致状态更新时整个应用都重新渲染影响性能。所以在选择状态管理方案时一定要根据应用的复杂度来决定。对于小型应用React Context useReducer可能就足够了对于中型应用可以考虑Zustand或Jotai对于大型应用Redux或MobX可能更合适。当然状态管理也不是万能的。良好的组件设计和代码组织同样重要。如果你的组件设计不合理即使使用了最好的状态管理库也无法解决根本问题。最后记住一句话状态管理的目的是为了简化状态管理而不是为了增加复杂度。如果你的状态管理方案让代码变得更复杂那你就失败了。