React中使用useReducer
1.Reducer
*使用函数组件来对
state
的数据进行多次修改的话,就可以使用useReducer来对其内容进行简化。
const [count, setCount] = useState(1)
// 增加
const addHandler = () => {
setCount(prevState => prevState + 1 )
}
// 减少
const subHandler = () => {
setCount(prevState => prevState - 1 )
}
return (
<div>
<button onClick={subHandler}> - </button>
{count}
<button onClick={addHandler}> + </button>
</div>
)
每次调用的话都要
setCount
useReducer(reducer, initialArg, init)
useRecucer有三个参数
/*
参数:
reducer: 函数 该函数的返回值会成为state的
新值
initialArg:state的初始值,作用和
useState()
的值是一样的 reducer在执行的时候会受到两个参数:
> 第一个参数为当前最新的state
> action 需要一个对象,在对象中存储dispatch的指令
返回值:
数组:
第一个参数:state 用来获取state的值
第二个参数:state 修改的派发器
具体的修改行为将会由
另外一个函数(reducer)
执行const [count, countDispatch] = useReducer(()=>{}, 1)
*/
-
增加
const [count, countDispatch] = useReducer((state, action)=>{ // 第一个参数为当前最新的state console.log("执行reducer", state) console.log("执行reducer", action) // 可以根据action中不同的type来执行不同的操作 // if(action.type === 'add'){ // return state + 1 // }else if (action.type === 'sub') { // return state - 1 // } // return state switch(action.type){ case 'add' : return state + 1; case 'sub' : return state - 1; default: return state } // return state + 1 // 增加 }, 1) const addHandle = () => { countDispatch({type:'add'}) } const subHandle = () => { countDispatch({type:'sub'}) }
-
注:
-
为了避免reducer会重复创建,通常reducer会定义在组件的外部,以减少它重复创建的次数!!!!!!!!!!!!!!
-
useReducer会返回由两个值组成的数组:
1.当前的state,初始值2.dispatch函数,可以根据交互来修改state的值
-
// 在组件外部
const countReducer = (state, reducer) => {
switch(action.type){
case 'add' :
return state + 1;
case 'sub' :
return state - 1;
default:
return state
}
}
// --------------------------------------------
// 在组件里面
const [count, countDispatch] = useReducer(countReducer, 1)
const addHandle = () => {
countDispatch({type:'add'})
}
const subHandle = () => {
countDispatch({type:'sub'})
}
完整代码:
import React, { useState, useReducer } from "react";
import Bottombar from "../components/Bottombar/Bottombar";
import Map from "../components/Map";
import { Outlet, Link } from "react-router-dom";
import "./phone.css";
// 为了避免回調函數reducer会重复渲染,因此要定义在组件外面
// 在组件外面
const reducer = (state, action) => {
console.log("state", state);
console.log("action", action);
switch (action.type) {
case "add":
return state + 1;
case "sub":
return state - 1;
// 默認返回
default:
return state;
}
};
const Phone = () => {
// 使用useState和useReducer
const [count, setcount] = useState(1);
const SubCount = () => {
console.log("-1");
setcount((prevState) => prevState - 1);
};
const AddCount = () => {
console.log("+1");
setcount((prevState) => prevState + 1);
};
// useReducer
// const [num, numDispatch] = useReducer(reducer, 11);
const [num, numDispatch] = useReducer(reducer, 11);
const SubReducerCount = () => {
numDispatch({ type: "sub" });
};
const AddReducerCount = () => {
numDispatch({ type: "add" });
};
return (
<div>
Phone
<br></br>
{/* <h1 className="bgc">test</h1> */}
<Link to="/phone/era" className="red">
eraeraeraera
</Link>
--------------------
<Link to="/phone/erc" className="red">
ercercercerc
</Link>
<Outlet></Outlet>
{/* <Map></Map> */}
<div>
<div className="title">使用useState和useReducer</div>
<div className="title">--使用useState</div>
<div className="box">
<button onClick={SubCount}>-1</button>
<div className="num">{count}</div>
<button onClick={AddCount}>+1</button>
</div>
<div className="title">--使用useReducer</div>
<div className="box">
<button onClick={SubReducerCount}>-1</button>
<div className="num1">{num}</div>
<button onClick={AddReducerCount}>+1</button>
</div>
</div>
<Bottombar></Bottombar>
</div>
);
}
export default Phone
如果是对象的话,以下方式写会有问题!!!!
// 在组件外面
const reducer = (state, action) => {
console.log("state", state);
console.log("action", action);
switch (action.type) {
case "add":
return state.age + 1;
case "sub":
return state.age - 1;
// 默認返回
default:
return state.age;
}
};
const [num, numDispatch] = useReducer(reducer, {
name: '李白',
age: 22
});
解决:
// 为了避免回調函數reducer会重复渲染,因此要定义在组件外面
// 在组件外面
const reducer = (state, action) => {
console.log("state", state);
console.log("action", action);
switch (action.type) {
case "add":
return {
name: 'author+',
age: state.age + 1
};
case "sub":
return {
name: 'author-',
age: state.age - 1
};
// 默认返回
default:
return {
name: '李白',
age: state.age
};
}
};
注意:state是只读的,不管是对象
还是数组
都不能去修改它,正确写法是返回新的对象
// 不可取的 ×
switch (action.type) {
case "add":
state.age = state.age + 1
return state;
......
// 正确写法:√
switch (action.type) {
case "add":
return {
name: 'author+',
age: state.age + 1
};