You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

useReducer hook极简讲解:工作原理与适用场景咨询

useReducer 通俗讲解

别整那些绕人的概念,本质上它就是个帮你管状态的工具,比你常用的useState更适合处理逻辑复杂的状态更新,你拿点外卖的逻辑套就行:

  • 你(页面组件)不需要自己记着状态要怎么改,只要说清楚你要做什么操作就行
  • 专门有个固定的“处理岗”(reducer函数)接你的操作要求,按提前写好的规则算出新的状态返回给你
  • 所有状态修改的逻辑全收拢在这一个岗位里,不会散在页面各个点击事件、回调里找不着
核心运行逻辑

整个机制就3个固定组成部分,跑起来流程也不绕:

3个必选零件

  • reducer处理函数
    就是个普通的纯JS函数,固定接收两个参数,返回新的状态,举个最简单的计数器例子:
    // 参数1:当前最新的旧状态  参数2:你发过来的操作指令
    function countReducer(state, action) {
      // 根据不同操作类型,返回对应的全新状态,绝对不能直接修改原state
      switch (action.type) {
        case 'increment':
          return state + 1
        case 'decrement':
          return state - 1
        case 'reset':
          return 0
        case 'addCustomNum':
          // 额外带的参数存在action.payload里就行
          return state + action.payload
        default:
          throw new Error('不存在的操作类型')
      }
    }
    
  • 初始状态值
    就是状态第一次渲染时的默认值,比如计数器初始是0,就写const initialCount = 0就行。
  • 调用Hook拿到的两个返回值
    写法和useState很像:
    const [count, dispatch] = useReducer(countReducer, initialCount)
    
    • 第一个返回值count就是当前的最新状态,和useState返回的状态值用法完全一样,直接绑在页面上渲染就行
    • 第二个返回值dispatch是你修改状态的唯一入口,想改状态只能调用它传操作指令,比如点加1按钮就写dispatch({ type: 'increment' }),要加指定数字就写dispatch({ type: 'addCustomNum', payload: 5 })

完整运行流程

总共就4步,没有任何黑魔法:

  1. 组件第一次加载时,useReducer直接拿你传的初始状态当当前值,渲染页面
  2. 你触发点击、输入这类交互时,调用dispatch方法传操作指令(action)
  3. React自动把当前的旧状态、你传的action丢进reducer函数里执行,拿到返回的新状态
  4. 如果新状态和旧状态不相等,React触发组件重渲染,页面展示最新的状态值
适用场景(别瞎用)

很多教程把useReducer吹得神乎其神,实际上大部分场景你用useState足够,满足以下任意一种情况再考虑用:

  • 单个状态的更新逻辑特别复杂、分支特别多:比如一个表单有输入校验、提交中、提交成功、提交失败、重置、字段联动等十几种更新逻辑,用useState你要写七八个set方法散在各个回调里,出bug找半天;用useReducer所有更新逻辑全在reducer一个函数里,排查问题、改逻辑都只需要看这一个地方
  • 状态更新逻辑要往深层子组件传:如果你的组件嵌套很深,要把好几个状态更新方法往下传三四层,用useReducer你只需要把一个dispatch传下去就行,子组件想触发什么更新直接调dispatch传对应指令,不用层层传递一堆set方法

划重点:如果只是管个弹窗显隐、输入框值这种只有两三种简单更新逻辑的状态,硬套useReducer纯属于脱裤子放屁,平白多写十几行代码,没有任何收益。

几个容易踩的坑
  • reducer必须是纯函数:别在里面写接口请求、操作DOM、修改全局变量这类有副作用的逻辑,它只负责“输入旧状态+指令,输出新状态”这一件事
  • 绝对不能直接修改原状态:如果你的状态是对象、数组这类引用类型,不能直接写state.userName = '李四'然后return原state,必须返回一个全新的引用,比如return { ...state, userName: '李四' },不然React检测不到状态变化,页面不会更新
  • action的格式没有强制要求:行业约定俗成传带type字段的对象,要带额外参数就放payload字段里,你要是图省事直接传字符串dispatch('increment')也能跑,但团队协作的时候别这么写,别人读你代码会懵

内容的提问来源于stack exchange,提问作者Prabhneet Singh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 02:01:12