【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 不会自动变化,仍然保持最新的值

相关推荐
福尔摩斯张33 分钟前
Axios源码深度解析:前端请求库设计精髓
c语言·开发语言·前端·数据结构·游戏·排序算法
李牧九丶1 小时前
从零学算法1334
前端·算法
周周爱喝粥呀1 小时前
UI设计原则和Nielsen 的 10 条可用性原则
前端·ui
小云朵爱编程2 小时前
Vue项目Iconify的使用以及自定义图标,封装图标选择器
前端·javascript·vue.js
前端大卫2 小时前
CSS 属性值 initial、unset 和 revert 的解析
前端
shimh_凉茶2 小时前
webpack+vue2打包分析视图插件 webpack-bundle-analyzer
前端·webpack·node.js
P***25392 小时前
JavaScript部署
开发语言·前端·javascript
一只小阿乐2 小时前
react 状态管理mobx中的行为模式
前端·javascript·react.js·mobx·vue开发·react开发
l***O5202 小时前
前端路由历史监听,React与Vue实现
前端·vue.js·react.js
超级战斗鸡2 小时前
React 性能优化教程:useMemo 和 useCallback 的正确使用方式
前端·react.js·性能优化