跳到主要内容

useReducer

面试速答(30 秒版 TL;DR)

  • useReducer 是另一种状态管理方式,适合状态转移逻辑复杂、多个分支共享同一套更新规则的场景。
  • 它的核心不是“更高级的 useState”,而是把“状态怎么变”统一收口到 reducer。
  • 特别适合:
    • 多个 action 驱动同一状态对象
    • 状态流转比较明确
    • 想把更新逻辑做成可测试的纯函数
  • React 18 里它仍是同步描述状态变更规则的 Hook,并不会自动变成全局状态管理。

1. 基本模型

useState 更像:

  • 我直接设置一个值

useReducer 更像:

  • 我派发一个动作
  • reducer 决定状态该怎么变

示例:

type Action =
| {type: 'increment'}
| {type: 'decrement'}

function reducer(state: number, action: Action) {
switch (action.type) {
case 'increment':
return state + 1
case 'decrement':
return state - 1
default:
return state
}
}

const [count, dispatch] = useReducer(reducer, 0)

2. 它适合什么场景

2.1 多分支状态更新

比如一个表单编辑器可能有:

  • 更新字段
  • 重置
  • 批量填充
  • 提交成功回写

如果全用多个 setState 分散写,逻辑容易散。

2.2 状态机味道更强的流程

例如:

  • idle
  • loading
  • success
  • error

这种“动作驱动状态流转”的问题,很适合 reducer 思维。

3. 为什么说 reducer 要尽量保持纯函数

reducer 最理想的形式是:

  • 输入旧状态和 action
  • 返回新状态
  • 不做副作用

这样有几个好处:

  • 更好测
  • 更容易复盘状态流转
  • 逻辑集中,不容易散到各处

副作用通常应该放在:

  • 事件处理函数
  • useEffect

而不是 reducer 里。

4. useReduceruseState 怎么选

4.1 用 useState 更合适的时候

  • 状态很简单
  • 只有一两种更新方式
  • 不需要统一动作模型

4.2 用 useReducer 更合适的时候

  • 多个更新入口
  • 状态逻辑越来越复杂
  • 多个字段之间有关联

5. React 18 面试高频答法

Q1:为什么 useReducer 适合复杂状态?

因为它把“更新规则”集中在 reducer,而不是散落在多个事件处理函数里。

Q2:它能替代 Redux 吗?

在局部组件状态范围内可以承担一部分角色,但它不自带:

  • 全局共享
  • DevTools
  • 中间件
  • 跨模块组织

所以它不是 Redux 的完整替代品。

Q3:dispatch 为什么常被认为比较稳定?

因为 React 会提供稳定的派发入口,这让它在依赖传递和 Context 组合时比较方便。

常见追问

1)可以配合 Context 用吗?

可以。常见做法就是 useReducer + useContext 组成一个轻量局部状态容器。

2)初始化很重怎么办?

可以用惰性初始化,把初始计算延后到首次需要时。

易错点/坑

  • reducer 里写副作用。
  • 明明状态很简单,也强上 useReducer,导致样板代码变多。
  • 把它误解成“天然全局状态管理”。

速记要点(可背诵)

  • useReducer:把状态更新规则收口到 reducer。
  • 适合复杂状态流转,不适合所有简单本地状态。
  • reducer 尽量保持纯函数,副作用放外面。