useReducer原理

120 阅读1分钟

useReducer用于函数组件中管理更复杂的状态逻辑。

useReducer的基本用法

import React, { useReducer } from "react";
const initialState = { count: 0 };

function reducer(state:any, action:any) {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      throw new Error();
  }
}
const ReducerTest: React.FC = () => {
  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>
  </div>;
};
export default ReducerTest;

useReducer的原理

1. reducer函数

reducer函数是一个纯函数,它接收当前状态和描述状态更新的action,并返回新的状态。

function reducer(state, action) {
  // 根据 action.type 返回新的状态
}

2. 状态存储与更新

在React内部,useReducer维护一个状态单元和一个调度函数。调度函数用于派发action,触发状态更新。

let currentHook = null;

function useReducer(reducer, initialState) {
  if (!currentHook) {
    // 第一次渲染时初始化 state
    currentHook = {
      state: initialState,
      dispatch: function (action) {
        // 使用 reducer 计算新状态
        currentHook.state = reducer(currentHook.state, action);
        // 触发重新渲染
        render();
      }
    };
  }

  // 返回当前状态和 dispatch 函数
  return [currentHook.state, currentHook.dispatch];
}

function render() {
  // 在实际 React 中,这里会重新渲染组件并更新 DOM
}

  1. Hook的调用顺序 useReducer的调用顺序必须保持一致。React使用这个顺序来关联顺序来关联状态和组件。如果调用顺序发生变化,状态就会错位,导致Bug。因此,Hook必须在函数组件的顶层调用,不能在循环、条件语句或嵌套函数中调用。

useReduceruseState对比

  • 适用场景
  1. useState适用于简单状态管理。
  2. useReducer适用于复杂状态逻辑或状态更新涉及多个子状态的情况。
  • 状态更新
  1. useState通过直接设置新状态来更新。
  2. useReducer通过dispatch action 和 reducer函数来更新。