【react】 useReducer 集中式管理组件的状态

useReducer 集中式管理组件的状态

1️⃣ 基本概念

useReducer 是 React 提供的 管理组件状态的一种 Hook ,功能上类似于 useState,但是它更适合状态逻辑复杂或依赖前一个状态的情况

它的核心思想:

  • 状态(state) 是不可变的。
  • 状态更新逻辑 写在一个函数里(Reducer)。
  • 通过 dispatch(action) 来触发状态更新,而不是直接 setState。

1.1 函数签名

scss 复制代码
const [state, dispatch] = useReducer(reducer, initialState, init?)

参数解释:

参数 说明
reducer 一个函数 (state, action) => newState,决定状态如何更新
initialState 初始状态
init 可选函数,用于惰性初始化状态(通常不需要)

返回值:

  • state:当前状态(只读)
  • dispatch:派发 action 的函数,用来触发状态更新

1.2 Reducer 函数

Reducer 是状态更新逻辑的核心:

php 复制代码
function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      return state;
  }
}

特点:

  • 不直接修改 state,而是返回一个新的状态对象
  • 通常使用 switch(action.type) 来判断不同动作。
  • action 可以是对象,也可以是任意自定义格式(推荐对象,包含 type 字段)。

1.3 最简单的例子

javascript 复制代码
import React, { useReducer } from 'react';

const initialState = { count: 0 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    case 'reset':
      return { count: 0 };
    default:
      return state;
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      <p>Count: {state.count}</p>
      <button onClick={() => dispatch({ type: 'increment' })}>+</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>-</button>
      <button onClick={() => dispatch({ type: 'reset' })}>Reset</button>
    </div>
  );
}

export default Counter;

✅ 可以看到:

  • 所有状态更新逻辑都集中在 reducer 里。
  • 组件内部不需要关心更新细节,只需要 dispatch 对应的 action。

2️⃣ useReducer vs useState

方面 useState useReducer
适用场景 简单状态(计数器、输入框) 复杂状态逻辑、多个子值依赖前一个状态
状态更新 setState(newValue) dispatch(action)
状态逻辑 分散在多个 setState 集中在 reducer 函数
可读性 简单 状态逻辑清晰、易于维护
性能优化 不如 useReducer dispatch 不会改变引用,可避免重复渲染

总结

  • 简单场景用 useState 就够了。
  • 状态更新复杂(多分支、多子值依赖)用 useReducer 更清晰。

3️⃣ 更复杂的例子:表单管理

假设有一个复杂表单:

javascript 复制代码
import React, { useReducer } from 'react';

const initialState = {
  username: '',
  email: '',
  password: '',
};

function reducer(state, action) {
  switch (action.type) {
    case 'updateField':
      return { ...state, [action.field]: action.value };
    case 'reset':
      return initialState;
    default:
      return state;
  }
}

function Form() {
  const [state, dispatch] = useReducer(reducer, initialState);

  const handleChange = (e) => {
    dispatch({ type: 'updateField', field: e.target.name, value: e.target.value });
  };

  const handleReset = () => {
    dispatch({ type: 'reset' });
  };

  return (
    <form>
      <input name="username" value={state.username} onChange={handleChange} placeholder="Username" />
      <input name="email" value={state.email} onChange={handleChange} placeholder="Email" />
      <input name="password" type="password" value={state.password} onChange={handleChange} placeholder="Password" />
      <button type="button" onClick={handleReset}>Reset</button>
    </form>
  );
}

export default Form;

✅ 优点:

  • 所有字段更新逻辑集中在 reducer 中。
  • 方便扩展,比如添加表单校验、提交状态等。

4️⃣ useReducer 的惰性初始化

有时候初始化 state 很复杂,可以用第三个参数 init

kotlin 复制代码
function init(initialCount) {
  return { count: initialCount };
}

const [state, dispatch] = useReducer(reducer, 0, init);

好处:

  • 性能优化 :只有第一次 render 会调用 init
  • 避免每次 render 都执行复杂计算。

5️⃣ 总结

  1. useReducer 是 useState 的增强版,适合复杂状态逻辑。

  2. 核心概念

    • Reducer:决定状态如何变化
    • State:组件状态(只读)
    • Dispatch:触发状态更新
  3. 优点

    • 状态更新逻辑集中,易维护
    • 方便管理复杂或嵌套状态
    • 和 Redux 思想一致,易迁移
  4. 使用场景

    • 多个状态值相互依赖

    • 多分支的状态更新逻辑

    • 想用 dispatch(action) 统一管理

总结

useReducer 管理的 state 本身只会在 dispatch 被调用时改变。每次组件重新渲染时,整个组件函数会重新执行,但 state 不会自动变化,仍然保持最新的值

相关推荐
掘金者阿豪14 分钟前
从Oracle迁到金仓,第一个月踩的最大的坑就是它
前端·后端
AZaLEan__29 分钟前
CSS文档流相关:BFC
前端·css
小林ixn42 分钟前
Vue3接入DeepSeek流式输出,把“二进制碎片”和“局部热更新”扒个精光
前端·vue.js·人工智能
2501_912784081 小时前
Taocarts 前端国际化实战:多语言与多币种怎么落地不翻车
前端·多语言·taocarts
悟空瞎说1 小时前
AI 流式对话页面滚动抖动深度优化实战
前端
秋天的一阵风1 小时前
🔥 ECMAScript 2026 来了!使用这些新特性,JS 代码直接少一半
前端·javascript·ecmascript 6
小堂子这厢有礼了1 小时前
Chet.Admin 权限模型:菜单级 + 按钮级 + 行级三层防护
前端·后端·信息可视化·前端框架·.net
Cobyte1 小时前
编译解析器的基础——状态模式与状态机的原理
前端·javascript·vue.js
IT_陈寒2 小时前
Vue的这个响应式陷阱,让我加班到凌晨三点
前端·人工智能·后端
2501_916007472 小时前
抓包工具对比 Charles、Fiddler、TraceEagle、Wireshark 与 Proxyman
前端·网络协议·ios·adb·https·fiddler·wireshark