Skip to content

useReducer

什么是 useReducer

useReducer 是一个用于集中管理状态的 react Hook,通过 dispatch 函数派发类型和数据给 actions 函数,达到修改 state 的目的。

它接收一个 reducer 函数、state 初始值、初始化参数 init(可选),返回一个 state 数据和 dispatch 函数,相当于是 useState 的 plus 版,reducer 函数就是我们自定义的处理 state 数据的方法。

useReducer 的使用

(1) 引入 useReducer

ts
import React, { Fragment, useReducer } from "react";

(2) 定义 reducer 函数

  • 最外层返回 state,dispatch

  • 中层 state,action

  • 底层 通过 action.type 来执行不同的业务逻辑

ts
function useCount() {
  // 中层 需要state,action 函数
  function reducer(state, action) {
    const result = { ...state }; // 这一步很关键。重新赋值
    // 内层 需要action.type来执行不同的业务逻辑
    switch (action.type) {
      case "add":
        return { count: result.count + action.payload };
      case "desc":
        return { count: result.count - action.payload };
      default:
        return result;
    }
  }
  // 最外层 他解构的结果就是[state,dispatch] 第二个参数就是初始化的值
  return useReducer(reducer, { count: 0 });
}

(3) 使用 useReducer

使用 dispatch 发送走 type 和 payload

js
function FunctionPage3() {
  const [state, dispatch] = useCount();
  return (
    <div>
      <Fragment>
        <div>{state.count}</div>
        <div onClick={() => dispatch({ type: "add", payload: 3 })}>
          点击增加三个
        </div>
        <div onClick={() => dispatch({ type: "desc", payload: 3 })}>
          点击减少三个
        </div>
      </Fragment>
    </div>
  );
}

useReducer 和 useContent 联合使用

  • 一般 useReducer 在某些特定的场景会替代到 useState

  • 我们在使用 useReducer 的时候,通常和 useContent 一起联合使用,这样省的逐层传递

创建 父组件 儿子组件 孙子组件

bash
|--- index.jsx
|--- components
|-------- Basic1.jsx
|-------- Basic2.jsx

父组件

js
import { Fragment, useReducer, useContext, createContext } from "react";
import Basic1Component from "./components/Basic1";

// 1. 创建Reducer
function useName() {
  function reducer(state, action) {
    const result = { ...state };
    switch (action.type) {
      case "changeName":
        result.name = action.payload;
        return result;
      case "changeAge":
        result.age = action.payload;
        return result;
      default:
        return result;
    }
  }
  return useReducer(reducer, { name: "张三", age: 18 });
}

// 2.创建 context
export const ContextComponent = createContext();

function FcuntionPage3() {
  // 使用reducer
  const [state, dispatch] = useName();
  return (
    <Fragment>
      <ContextComponent.Provider value={{ state, dispatch }}>
        <Basic1Component />
      </ContextComponent.Provider>
    </Fragment>
  );
}

export default FcuntionPage3;
  • 儿子组件
js
import Basic2Component from "./Basic2";
function Basic1() {
  return (
    <div>
      <Basic2Component />
    </div>
  );
}

export default Basic1;
  • 孙子组件
js
import React, { useContext } from "react";
import { ContextComponent } from "../index";
function Basic2() {
  const { state, dispatch } = useContext(ContextComponent);
  return (
    <div>
      <h1>
        {state.name}---{state.age}
      </h1>
      <button
        onClick={() => {
          dispatch({ type: "changeName", payload: "改变后的名字" });
        }}
      >
        改变名字
      </button>
      <button
        onClick={() => {
          dispatch({ type: "changeAge", payload: 48 });
        }}
      >
        改变年龄
      </button>
    </div>
  );
}

export default Basic2;