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
}
Hook的调用顺序useReducer的调用顺序必须保持一致。React使用这个顺序来关联顺序来关联状态和组件。如果调用顺序发生变化,状态就会错位,导致Bug。因此,Hook必须在函数组件的顶层调用,不能在循环、条件语句或嵌套函数中调用。
useReducer和useState对比
- 适用场景
useState适用于简单状态管理。useReducer适用于复杂状态逻辑或状态更新涉及多个子状态的情况。
- 状态更新
useState通过直接设置新状态来更新。useReducer通过dispatch action 和 reducer函数来更新。