React useReducer 复杂状态

React useReducer 复杂状态

前置:React Context 跨层传值

目标:会写 reducer(state, action);理解何时从 useState 升级。

引言

一个开关、一个输入框 → useState 最爽。

状态字段变多、更新规则互相牵扯时,一堆 setX / setY 容易乱。

useReducer :把「怎么从旧状态算出新状态」收进纯函数 reducer(state, action);组件里只 dispatch({ type: '...' })。

本篇 demo:计数器 + 可调步长 + 重置,四种 action。

动手

完整代码:react2/12-usereducer/demo

bash 复制代码
cd react2/12-usereducer/demo
npm install && npm run dev

改步长再点 +step / -step;点「重置」回到 count=0, step=1。


1. 定义 state / action / reducer

tsx 复制代码
type State = { count: number; step: number }
type Action =
  | { type: 'inc' }
  | { type: 'dec' }
  | { type: 'setStep'; step: number }
  | { type: 'reset' }

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case 'inc':
      return { ...state, count: state.count + state.step }
    case 'dec':
      return { ...state, count: state.count - state.step }
    case 'setStep':
      return { ...state, step: action.step }
    case 'reset':
      return { count: 0, step: 1 }
    default:
      return state
  }
}

约定:

  • 纯函数:同样输入 → 同样输出;不写副作用
  • 不可变更新 :返回新对象,别直接改 state.count = ...
  • action.type 描述「发生了什么」,不是「把 count 设成几」

2. 组件里 dispatch

tsx 复制代码
const [state, dispatch] = useReducer(reducer, { count: 0, step: 1 })

<button onClick={() => dispatch({ type: 'inc' })}>+step</button>
<button onClick={() => dispatch({ type: 'dec' })}>-step</button>
<button onClick={() => dispatch({ type: 'reset' })}>重置</button>
<input
  type="number"
  value={state.step}
  onChange={(e) =>
    dispatch({ type: 'setStep', step: Number(e.target.value) || 1 })
  }
/>

UI 只发意图;怎么改状态全在 reducer。


3. 何时从 useState 升级

继续 useState 考虑 useReducer
单个布尔 / 字符串 下一状态严重依赖上一状态
字段少、更新简单 同一状态有多种「动作」
想把更新逻辑抽到组件外测

useReducer + Context 常一起做中等复杂度的客户端状态;更大更碎的全局状态看 Zustand(15 篇)。


4. 常见坑

做法 问题
reducer 里 fetch / 改 DOM 副作用放错地方;副作用进 event / effect
直接 mutate state React 可能检测不到更新
action 设计成「setCount(5)」一堆 丢失「意图」;能工作但难推理
简单开关也上 reducer 过度;useState 更短

demo 在练什么

  1. 手写 State / Action / reducer
  2. 用 dispatch 驱动多动作更新
  3. 体会「步长影响加减」这种跨字段规则放在 reducer 里更清晰

自己改一改:加 type: 'double';或把初始 state 换成惰性初始化 useReducer(reducer, undefined, init)。


下一篇

React 嵌套路由与布局

相关推荐
古茗前端团队1 天前
由 key 引发的思考
前端·javascript·react.js
用户298698530144 天前
React 前端将 Excel 工作表导出为图片的技术实践
javascript·react.js·excel
終不似少年遊*5 天前
【安全业务Agent】从场景到编排
python·react.js·ai·langchain·agent·安全架构·工作流
JavaPub-rodert6 天前
从零搭建通用管理后台:ShiyuAdmin 的 Go、React 与 RBAC 实践
开发语言·react.js·golang
Highcharts.js6 天前
React 中原生支持使用 JSX 组件配置自定义表格 Highcharts Grid
前端·javascript·react.js·前端框架·jsx·highcharts·自定义表格
JudithHuang6 天前
React 嵌套路由与布局
前端·react.js·arcgis·react·react router
前端小D6 天前
React Native项目开发(iOS侧为例)
javascript·react native·react.js
志尊宝7 天前
AI原生前端开发(042):AI辅助的路由设计与优化
javascript·react.js·ai-native
znsoft8 天前
MaClaw(码卡龙)技术拆解:一个 Go + React 的可自进化智能体平台
开发语言·react.js·golang
濮水大叔8 天前
React/Next.js 生态里,有没有 CabloyJS 这样的全栈框架?
react.js·全栈·next.js