先大概说下
React 官方在Hooks出来之后,并没有强推Redux,MobX 这类第三方库,而是建议先使用内置的Hooks组合起来做状态管理。
- useReducer : 管理复杂状态更新逻辑
- useContext : 解决多层组件传参的问题
结合起来就像是一个迷你Redux
useReducer
= Redux 的 reducer + dispatchuseContext
= Redux 的 Provider/Store 订阅机制
- 优点:
- 无需额外依赖,纯Redux内置
- 类型安全(TS友好)
- API简单,学习成本低
- 状态集中管理,避免props层层传递
各自作用回顾
- useReducer
- 适合复杂状态逻辑: 状态是一个对象/数组,多种不同更新方式
- 接受
(state, action) => newState
形式的reducer函数
- useContext
- 用于跨组件共享数据,避免父子组件层层传递props
- 配合Provider包裹整个组件树,子组件直接拿到共享数据
如何配合使用?
- 在顶层使用useReducer 管理全局状态
- 用useContext把state 和 dispatch 共享给所有子组件
- 子组件直接
dispatch({type:'xxx',payload:...})
更新全局状态 - 总结:实际上就是把改变全局状态的方法提供给了所有子组件
小例子:计数器
tsx
import React,{useReducer,createContext,useContext} from 'react';
// 1️⃣ 创建 Context
const CountContext = createContext(null);// 之后使用<CountContext.Provider>把子组件包起来,形成一个上下文区域
// 2️⃣ Reducer(专管状态更新)
function countReducer(state, action) {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
// 3️⃣ Provider(集中管理 state + dispatch)
function ContProvider({children}){
const [state,dispatch] = useReducer(counter,{count:0});
return (
<CountContext.Provider value={{ state, dispatch }}>
{children}
</CountContext.Provider>
);
}
// 4️⃣ 自定义 Hook(方便子组件用)
function useCount() {
const context = useContext(CountContext);
if (!context) throw new Error('useCount 必须在 CountProvider 中使用');
return context;
}
// 5️⃣ 子组件
function Counter() {
const { state, dispatch } = useCount();
return (
<div>
<h2>Count: {state.count}</h2>
<button onClick={() => dispatch({ type: 'increment' })}>+1</button>
<button onClick={() => dispatch({ type: 'decrement' })}>-1</button>
</div>
);
}
// 6️⃣ App 入口
export default function App() {
return (
<CountProvider>
<h1>useContext + useReducer 最小例子</h1>
<Counter />
</CountProvider>
);
}
这个例子里做了什么?
CountContext
:像"广播站",负责全局共享数据。countReducer
:状态修改的唯一入口(类似 Redux 里的 reducer)。CountProvider
:状态+dispatch 的容器,包裹住所有需要共享状态的组件。useCount()
:封装 useContext,保证用起来更简洁。Counter
:子组件可以直接dispatch
来修改全局状态。