如何使用useReducer

我的GitHub

useReducer 是 React 的一个 Hook,用于处理组件的复杂状态逻辑。与 useState 不同,useReducer 允许你以更可预测的方式管理组件的多个状态字段。

基本用法

useReducer 接受一个 reducer 函数和一个初始状态作为参数,并返回一个包含当前状态和一个 dispatch 方法的数组。reducer 函数接受当前的状态和一个 action,并返回一个新的状态。

这里是一个简单的计数器示例:

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 };
    default:
      throw new Error();
  }
}

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

  return (
    <>
      Count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>Increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>Decrement</button>
    </>
  );
}

参数

  1. reducer: 这是一个纯函数,接受当前状态和一个动作对象,返回一个新的状态。
  2. initialState: 这是 reducer 的初始状态。
  3. init: (可选) 如果提供,这个函数会接受 initialState 作为参数并返回初始状态值。

返回值

useReducer 返回一个数组,其中包含两个元素:

  1. state: 当前状态。
  2. dispatch: 这是一个方法,用于触发 reducer 动作。

动作(Action)

动作通常是一个具有 type 属性的对象,该属性描述了发生了什么,以及一个 payload 属性,该属性包含需要更新状态的任何信息。但实际上,动作可以是任何值(如字符串、数字或对象)。

何时使用 useReducer

  • 当你需要处理多个互相关联的状态字段时。
  • 当你需要处理复杂的状态逻辑,该逻辑包含多个子值或下一个状态依赖于之前的状态时。
  • 当你需要明确地跟踪状态更改的来源时,例如实现撤消/重做功能。

总体来说,useReducer 提供了一种更强大、更可预测的方式来管理组件状态。

举个usestate不能做而usereducer可以做的例子

当你有多个相互依赖的状态字段,且状态更新逻辑相当复杂时,useReducer 通常更合适。考虑一个购物车组件的例子,其中有多个状态字段:商品列表、总价、折扣等。这些字段可能依赖于其他字段的状态。

import React, { useReducer } from "react";

const initialState = {
  items: [], // 商品列表
  total: 0,  // 总价
  discount: 0 // 折扣
};

const reducer = (state, action) => {
  switch (action.type) {
    case "ADD_ITEM":
      const newItems = [...state.items, action.item];
      const newTotal = newItems.reduce((acc, item) => acc + item.price, 0);
      return {
        ...state,
        items: newItems,
        total: newTotal
      };
    case "APPLY_DISCOUNT":
      return {
        ...state,
        discount: action.discount,
        total: state.total * (1 - action.discount / 100)
      };
    default:
      return state;
  }
};

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

  const addItem = (item) => {
    dispatch({ type: "ADD_ITEM", item });
  };

  const applyDiscount = (discount) => {
    dispatch({ type: "APPLY_DISCOUNT", discount });
  };

  return (
    <div>
      <h1>Shopping Cart</h1>
      {/* 商品列表和添加商品操作 */}
      {/* ... */}
      <button onClick={() => addItem({ name: "Apple", price: 1 })}>
        Add Apple
      </button>
      {/* 显示总价 */}
      <p>Total: ${state.total}</p>
      {/* 应用折扣 */}
      <button onClick={() => applyDiscount(10)}>Apply 10% Discount</button>
    </div>
  );
}

在这个例子中,当你添加一个商品(ADD_ITEM)时,不仅 items 状态会改变,total(总价)也需要更新。当应用折扣(APPLY_DISCOUNT)时,discounttotal 都需要更新。

如果使用 useState,你需要手动同步这些状态,这会使代码更难管理和调试。通过使用 useReducer,你可以将所有相关的逻辑放在一个地方,使状态更新更可预测和可维护。

猜你喜欢

转载自blog.csdn.net/m0_57236802/article/details/133376675
今日推荐