useReducer
是 React 中用于管理复杂状态逻辑的 Hook,它通过 集中式状态更新逻辑 替代 useState
,尤其适合处理多值关联状态或依赖前序状态更新的场景。以下是其核心要点:
1. 核心概念
- Reducer 模式:灵感来自 JavaScript 的
Array.prototype.reduce
和 Redux,通过(state, action) => newState
函数管理状态变更。 - 返回值:返回当前状态
state
和派发函数dispatch
,例如:const [state, dispatch] = useReducer(reducer, initialState);
2. 参数解析
参数 | 说明 |
---|---|
reducer | 纯函数,接收当前状态和 action ,返回新状态。常用 switch/case 处理不同 action.type 。 |
initialState | 初始状态值(如 { count: 0 } )。 |
init函数 | (可选)惰性初始化,将初始状态计算逻辑封装(如从 localStorage 读取)。 |
3. 工作流程
- 派发 Action:调用
dispatch({ type: 'increment' })
触发状态更新。 - Reducer 处理:根据
action.type
计算新状态(需返回全新对象,不可直接修改原状态)。 - 组件渲染:状态更新后组件重新渲染。
4. 对比 useState
特性 | useReducer | useState |
---|---|---|
适用场景 | 复杂逻辑、多关联状态 | 简单独立状态 |
代码组织 | 逻辑集中,易于维护 | 逻辑分散在多个 setState |
性能优化 | 可避免深层传递回调 | 需手动优化 |
5. 典型示例
计数器应用
function reducer(state, action) {switch (action.type) {case 'increment':return { count: state.count + 1 };case 'decrement':return { count: state.count - 1 };default:throw new Error();}
}function Counter() {const [state, dispatch] = useReducer(reducer, { count: 0 });return (<>Count: {state.count}<button onClick={() => dispatch({ type: 'increment' })}>+</button></>);
}
惰性初始化
function init(initialCount) {return { count: initialCount };
}function reducer(state, action) {// ...同上
}function Counter({ initialCount }) {const [state, dispatch] = useReducer(reducer, initialCount, init);// ...
}
6. 使用场景
- 复杂状态对象:如表单、多步骤向导。
- 性能敏感场景:避免子组件不必要的渲染(通过传递
dispatch
而非回调)。 - 状态依赖前值:如
state.count + action.payload
。
7. 注意事项
- 纯函数要求:Reducer 必须无副作用,不直接修改
state
。 - 异步问题:
dispatch
后立即读取state
仍是旧值(更新是异步的)。 - SSR 兼容:需注意服务端渲染时的初始化逻辑。
总结
useReducer
通过集中管理状态变更逻辑,提升了代码可维护性和可预测性,适合中大型应用的复杂状态管理。结合 useContext
可进一步替代 Redux 等状态库。