标准答案
- useState 适合简单值或少量独立状态,例如开关、输入值、当前页码、选中 id。
- useReducer 适合多个字段一起变化、更新逻辑复杂、状态转移需要集中管理的场景。
- reducer 接收当前 state 和 action,返回下一次 state,便于把状态变化规则收敛到一个函数里。
- useReducer 不等于全局状态管理,它仍然是组件内或局部组件树内的状态方案。
- 如果只是简单 setOpen(true),用 useReducer 会过度设计;如果多个 setState 互相依赖,useReducer 更清晰。
题目解析
这道题可以从复杂度和状态转移规则回答。状态越像一个小状态机,越适合 useReducer。
useReducer 的优势是让更新动作语义化,例如 submit、success、error、reset,而不是散落多个 setState。
配合 context 可以把局部状态和 dispatch 传给子树,但要注意 context 更新带来的渲染范围。
代码示例
下面用 reducer 管理请求状态,避免 loading、data、error 三个状态互相打架。
TSX
type State = {
loading: boolean
data: User | null
error: string
}
type Action =
| { type: 'start' }
| { type: 'success'; data: User }
| { type: 'error'; error: string }
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'start':
return { loading: true, data: null, error: '' }
case 'success':
return { loading: false, data: action.data, error: '' }
case 'error':
return { loading: false, data: null, error: action.error }
}
}常见误区
- 简单布尔开关也用 useReducer,增加样板代码。
- reducer 里直接修改原 state,而不是返回新对象。
- 把 useReducer 当成 Redux 替代品,忽略它默认只管理当前组件局部状态。