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;