【React】React18 Hooks 之 useReducer
目录
useReducer
useReducer是一个 React Hook,可让你向组件添加一个Reducer 。
用法:
const [state, dispatch] = useReducer(reducer, initialArg, init?)
- reducer:指定状态如何更新的 Reducer 函数,接受两个参数state(状态)和action(操作)两个参数,并返回下一个状态
- initialArg:初始值,可以是任何类型的值
- 可选 init:应返回初始状态的初始化函数。如果未指定,则将初始状态设置为initialArg。否则,将初始状态设置为调用的结果init(initialArg)
useReducer返回一个包含两个值的数组:
- state(当前状态):在第一次渲染期间,它被设置为init(initialArg)或initialArg(如果没有init)
- dispatch:该dispatch函数可让您将状态更新为不同的值并触发重新渲染
案例1:useReducer不带初始化函数
步骤:
1、定义一个reducer函数,根据不同的action返回不同的状态
2、组件中调用userReducer(reducer,initialArg)
3、调用dispatch({type:“INC”})通知reducer产生一个新的状态,随后更新UI
const idata = {count:0};
function reducer(state, action) {
console.log(state,"state")
console.log(action,"action")
switch (action.type) {
case "INC":
return {count:state.count+1}
case "DEC":
return {count:state.count-1}
case "SET":
return {count:action.payload}
default:
return {count:idata}
}
}
function App() {
const [state, dispatch] = useReducer(reducer, idata);
return (
<div className="App">
this is App
{state.count}
<button onClick={() => dispatch({ type: "INC" })}>+</button>
<button onClick={() => dispatch({ type: "DEC" })}>-</button>
<button onClick={() => dispatch({ type: "SET", payload: 100 })}>update</button>
</div>
);
}
export default App;
案例2:useReducer带初始化函数
设置initData为初始化函数,设置state初始状态
#App.js
import Son from "./Son.js";
function App() {
return (
<div className="App">
<Son idata={{count:1}}></Son>
</div>
);
}
export default App;
#Son.js
import { useReducer } from "react";
const initData=()=>{
return {count:0}
}
function reducer(state, action) {
console.log(state,"state")
console.log(action,"action")
switch (action.type) {
case "INC":
return {count:state.count+1}
case "DEC":
return {count:state.count-1}
case "SET":
return {count:action.payload}
default:
return initData()
}
}
const Son = ({idata})=> {
console.log(idata,"idata")
const [state, dispatch] = useReducer(reducer, idata,initData);
return (
<div className="App">
this is App
<div>Count: {state.count}</div>
<button onClick={() => dispatch({ type: "INC" })}>+</button>
<button onClick={() => dispatch({ type: "default" })}>default</button>
<button onClick={() => dispatch({ type: "DEC" })}>-</button>
<button onClick={() => dispatch({ type: "SET", payload: 100 })}>update</button>
</div>
);
}
export default Son;
注意事项1:dispatch函数不会改变正在运行的代码的状态
点击update按钮,handler函数触发之后,页面Count显示为100,但是打印出来state.count为0
dispatch函数不会改变正在运行的代码的状态,更新状态会请求使用新状态值进行另一次渲染,但不会影响state已在运行的事件处理程序中的 JavaScript 变量。
#Son.js
import { useReducer } from "react";
const initData = () => {
return { count: 0 }
}
function reducer(state, action) {
switch (action.type) {
case "INC":
return { count: state.count + 1 }
case "DEC":
return { count: state.count - 1 }
case "SET":
return { count: action.payload }
default:
return initData()
}
}
const Son = ({ idata }) => {
const [state, dispatch] = useReducer(reducer, idata, initData);
const handler =()=>{
dispatch({ type: "SET", payload: 100 })
console.log(state.count,"state")
setTimeout(()=>{
console.log(state.count,"state")
},1000)
}
return (
<div className="App">
this is App
<div>Count: {state.count}</div>
<button onClick={() => dispatch({ type: "INC" })}>+</button>
<button onClick={() => dispatch({ type: "default" })}>default</button>
<button onClick={() => dispatch({ type: "DEC" })}>-</button>
<button onClick={() => handler()}>update</button>
</div >
);
}
export default Son;
注意事项2:获取dispatch函数触发后 JavaScript 变量的值
执行reducer(state, action)之后,就可以拿到最新的变量的值
const handler =()=>{
let action = { type: "SET", payload: 100 };
dispatch(action)
console.log(state,"state") //打印0
setTimeout(()=>{
console.log(state,"state") //打印0
},1000)
const nextState = reducer(state, action);
console.log(nextState,'nextState') //打印100
}
注意事项3:触发了reducer,但页面没有更新
直接更改状态中的对象或数组,并不会重新渲染。因为下一个状态等于前一个状态,则React 将忽略您的更新Object.is,指向的还是同一个引用地址。所以需要始终更新状态中的对象和状态中的数组。如下:
function reducer(state, action) {
switch (action.type) {
case 'incremented_age': {
// ✅ Correct: creating a new object
return {
...state,
age: state.age + 1
};
}
case 'changed_name': {
// ✅ Correct: creating a new object
return {
...state,
name: action.nextName
};
}
// ...
}
}
原文地址:https://blog.csdn.net/qq_38951259/article/details/140211795
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!