介绍
useReducer 是 React 官方参考 Redux 第三方库的思想设计的 Hook,可以看做 useState 的高级版,用事件分发机制处理复杂的状态变化
不过 y1s1,实际开发中用得很少,因为写起来比较啰嗦,还不如 useState 一把梭
示例
把 App.tsx 文件内容替换为下面的代码
type TInitialState = {
count: number;
};
const initialState: TInitialState = {
count: 0,
};
type TReducer = (s: TInitialState, a: TAction) => TInitialState;
type TAction =
| {
type: "resetCount";
}
| {
type: "setCount";
payload: number;
};
const reducer: TReducer = (state, action) => {
switch (action.type) {
case "resetCount":
return {
...state,
count: 0,
};
case "setCount":
return {
...state,
count: action.payload,
};
default:
throwBadPet(action);
}
};
// Externally-visible signature
function throwBadPet(p: never): never;
// Implementation signature
function throwBadPet(p: TAction) {
throw new Error("Unknown pet kind: " + p);
}
const App: React.FC = () => {
const [state, dispatch] = React.useReducer(reducer, initialState);
return (
<div>
<h1>{state.count}</h1>
<button onClick={() => dispatch({ type: "resetCount" })}>resetCount</button>
<br />
<br />
<button onClick={() => dispatch({ type: "setCount", payload: state.count + 1 })}>setCount</button>
</div>
);
};
export default App;
将 useState 一同列出方便对比:
const [state, setState] = React.useState(initialState)
const [state, dispatch] = React.useReducer(reducer, initialState)
- state:取值,同 useState 的 state
- dispatch:设值,不像 useState 的 setState 可以直接设值,需要传 type 和 playload
- reducer:设值逻辑,根据传进来的 type 和 playload 处理
- initialState:初始状态,初始化是必要的
可以看到 useReducer 就相当于把 useState 的 setState 拆成了两部分: dispatch 和 reducer,开发者不能直接去更新状态了
另外,这里用 TS 声明了多个类型,稍微解释一下
- TInitialState 初始化状态
这里为了方便新手理解,只放了一个变量,实际项目中应该是有多个变量,多个状态之间复杂的管理才能体现出 useReducer 的优势 - TReducer 执行函数类型
这里定义了 throwBadPet 函数来对未匹配的 switch 值抛出异常,方便以后快速定位问题 - TAction 动作类型
这里定义需要的全部动作,方便后续使用,充分利用 TS 的类型检查机制