标准答案

  1. useState 适合简单值或少量独立状态,例如开关、输入值、当前页码、选中 id。
  2. useReducer 适合多个字段一起变化、更新逻辑复杂、状态转移需要集中管理的场景。
  3. reducer 接收当前 state 和 action,返回下一次 state,便于把状态变化规则收敛到一个函数里。
  4. useReducer 不等于全局状态管理,它仍然是组件内或局部组件树内的状态方案。
  5. 如果只是简单 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 替代品,忽略它默认只管理当前组件局部状态。

作者信息