当前位置: 首页 > news >正文

【React】React18 Hooks 之 useReducer

目录

  • useReducer
    • 案例1:useReducer不带初始化函数
    • 案例2:useReducer带初始化函数
    • 注意事项1:dispatch函数不会改变正在运行的代码的状态
    • 注意事项2:获取dispatch函数触发后 JavaScript 变量的值
    • 注意事项3:触发了reducer,但页面没有更新

在这里插入图片描述

React官方文档

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") //打印0setTimeout(()=>{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 objectreturn {...state,age: state.age + 1};}case 'changed_name': {// ✅ Correct: creating a new objectreturn {...state,name: action.nextName};}// ...}
}
http://www.lryc.cn/news/395765.html

相关文章:

  • 【cocos creator】2.4.x实现简单3d功能,点击选中,旋转,材质修改,透明材质
  • Android EditText+ListPopupWindow实现可编辑的下拉列表
  • dify/api/models/task.py文件中的数据表
  • hdu物联网硬件实验3 按键和中断
  • pytorch通过 tensorboardX 调用 Tensorboard 进行可视化
  • linux查看目录下的文件夹命令,find 查找某个目录,但是不包括这个目录本身?
  • 单一设备上的 2 级自动驾驶:深入探究 Openpilot 的奥秘
  • 向github远程仓库中push,要求使用token登录
  • 最全windows提权总结(建议收藏)
  • Could not find Chrome (ver.xxxxx). This can occur if either\n
  • Conmi的正确答案——ESP32-C3开启安全下载模式
  • 从零开始实现大语言模型(一):概述
  • 科普文本分类背后的数学原理——最新版《数学之美》第14、15章读书笔记
  • 华为云生态和快速入门
  • 卷积神经网络——LeNet——FashionMNIST
  • k8s-第十二节-DaemonSet
  • Mysql-内置函数
  • 新浪API系列:支付API打造无缝支付体验,畅享便利生活(3)
  • 终于弄明白了什么是EI!
  • 微信小程序常见页面跳转方式
  • Vim常用整理快捷键
  • 【docker 把系统盘空间耗没了!】windows11 更改 ubuntu 子系统存储位置
  • 前端如何让网页页面完美适配不同大小和分辨率屏幕
  • gitlab-runner安装部署CI/CD
  • 数据分析案例-2024 年全电动汽车数据集可视化分析
  • H桥驱动器芯片详解
  • 哪个充电宝口碑比较好?怎么选充电宝?2024年口碑优秀充电宝推荐
  • Memcached 介绍与详解及在Java Spring Boot项目中的使用与集成
  • 淮北在选择SCADA系统时,哪些因素会影响其稳定性?
  • Linux: 命令行参数和环境变量究竟是什么?