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

React第十五节useReducer使用详解差异

useReducer() 的用法注意事项

1、 概述:

useReducer() 常用于管理复杂的状态更新逻辑,特别是在状态更新依赖于多个条件动作时useReducer 提供了一种更加结构化和可维护的方式来处理状态。可以将更新函数写在组件外面
它与 useState() 相似,useState() 用于处理相对简单的状态更新逻辑

2、什么是useReducer():

它是React 提供的一个 HOOK,用于处理复杂的状态管理,特别是更新逻辑比较复杂,或者有多个状态相互依赖的逻辑业务中;

useReducer(reducer, initialArg, init?) 接收三个参数
第一个参数:reducer 用于更新 state纯函数,function(state, action) {};函数接收两个参数 state、action
其中 state 是只能读取的状态值,不能在纯函数里面进行直接修改
其中 action 是用户进行操作的函数,
第二个参数initialArg:用于初始化 state 的任意值,在没有第三个参数时候,直接取当前值为默认值,
第三个参数:init:为可选参数,用于处理state 的默认值函数

3、基本写法:

const [count, dispatch] = useReducer(reducer, initState, initFunc)

useReducer(): 利用数组解构,得到两个参数,
count:当前state的初始值,
dispatch:用于触发count 更新的分发函数;
通常为一个包含type属性的对象;如

const [count, dispatch] = useReducer(reducer, {count: 1}, initFunc)
function handleDispatch() {dispatch({type: 'ADD'})
}

4、 具体使用例子

国庆出游计划 增删改成游玩项目

4.1 、声明reducer逻辑处理函数

注意:跟useState 一样,修改数组、对象时候,需要修改其指针,否则React视为当前值没有发生改变

// taskReducer 文件
export default function taskReducer(tasks, action) {switch(action.type) {case 'added':{return [...tasks,{id: action.id,text: action.text,done: false,}]}case 'changed' : {return tasks.map(itm => {if (itm.id === action.task.id) {return action.task} else {return itm}})}case 'deleted' : {return tasks.filter(itm => itm.id!== action.id)}}
}

a、在 reducer 函数中 通常我们会使用 switch 进行处理type类型条件,当然了你也可以使用if() {}语句,
btaskReducer 函数中设计了新增、删除、修改三个类型;
c、根据传入的 action 中type类型来处理更新 tasks 的状态;

4.2、在组件中使用 useReducer

声明一个任务组件TaskApp

import { useState, useReducer } from 'react'
import taskReducer from './taskReducer'// ...
export default function TaskApp() {const [tasks, dispatch] = useReducer(taskReducer, initialTasks)//...
}
// 声明初始值
const initialTasks = [{id: 0, text: '参观卡夫卡博物馆', done: true},{id: 1, text: '看木偶戏', done: false},{id: 2, text: '打卡列侬墙', done: false}
];

此时我们得到一个tasks 初始值,以及一个dispatch 分发函数
通过调用 dispatch 来触发 taskReducer 函数中对应条件执行
比如要删除一个旅游项目

// ...
function handleDeleteTask(taskId) {dispatch({type: 'deleted',  // 直接传入 type类型为 deleted,id: taskId,})
}
// ...

4.3、完整代码

// TaskApp 组件文件
import { useReducer } from 'react'
// 新增旅游项目组件
import AddTask from './taskAdd'
// 旅游项目列表组件
import TaskList from './taskList'
export default function TaskApp() {const [tasks, dispatch] = useReducer(taskReducer, initialTasks)// 使用dispatch 触发新增操作function handleAddTask(text) {console.log('==handleAddTask=', nextId)dispatch({type:'added',id: nextId++,text: text,})}function handleChangeTask(task) {console.log('=handleChangeTask==', task)dispatch({type:'changed',task: task})}// 删除操作function handleDeleteTask(taskId) {dispatch({type: 'deleted',id: taskId,})}return (<><h1 style={{color: 'red'}}>国庆旅游计划</h1><AddTask onAddTask={handleAddTask}></AddTask><TaskList tasks={tasks}onChangeTask={handleChangeTask}onDeleteTask={handleDeleteTask}></TaskList></>)
}
let nextId = 3;

AddTask 组件中,新增操时候 重置了input 输入框的值,
同时给父组件传递了onAddTask 函数,触发父组件中的 handleAddTask 函数执行;

// AddTask 文件
import { useState } from 'react'
export default  function AddTask ({onAddTask}) {const [text, setText] = useState('')console.log('===useState==', useState())// 通过useState 的setText 触发视图更新function handleChangeText(text) {setText(text)}return (<><input type="text" value={text} onChange={e => handleChangeText(e.target.value)} /><button onClick={() => {setText('')onAddTask(text)}}>新增</button></>)}

TaskList 文件中传入 最新的 tasks 以及修改onChangeTask、删除onDeleteTask 函数

// TaskList 文件
export default function TaskList ({tasks, onChangeTask, onDeleteTask}) {return (<><ul>{tasks.map((itm, index) =>{return (<li key={itm.id}><span>{index + 1}</span><input type="text" value={itm.text} onChange={(e) => onChangeTask({...itm, text: e.target.value})}/><button onClick={() => onDeleteTask(itm.id)}>Delete</button></li>)})}</ul></>)
}

useReducer 与 useState相比较

异同

1、useReducer 更倾向于处理多逻辑状态,useState 倾向于处理单逻辑状态;
2、useReducer 可以处理 所有 useState 处理的 更新的属性
3、都必须在最组件的最顶层调用不能条件语句或者循环中使用;
4、初始化的时候 都会被调用 两次用于检查代码中的意外不纯粹性;
5、都可以触发视图更新

useReducer 的优缺点

优点:

代码统一组织管理:reducer 使得状态更新逻辑更加清晰,可以将不同的更新逻辑集中在一个地方,避免了多个 useState 带来的管理混乱。
方便调试reducer 是一个纯函数,给出明确的状态变化规则,便于调试日志记录。
用于复杂状态管理:对于复杂的状态更新,useReducer 是一种优于 useState 的解决方案,尤其是当状态变化需要依赖于多个值时。

缺点:

代码复杂:与 useState 相比,useReducer 需要写更多的代码,尤其是对于简单的状态管理,它的使用可能显得有些过于复杂。
学习成本高:对于 React 新手来说,理解 reducer 函数的工作方式可能需要一些时间,尤其是对于不熟悉 Redux 的开发者。

仅代表个人观点,如有出入欢迎批评指正

相关文章:

React第十五节useReducer使用详解差异

useReducer() 的用法注意事项 1、 概述&#xff1a; useReducer() 常用于管理复杂的状态更新逻辑&#xff0c;特别是在状态更新依赖于多个条件或动作时&#xff0c;useReducer 提供了一种更加结构化和可维护的方式来处理状态。可以将更新函数写在组件外面 它与 useState() 相…...

NanoLog起步笔记-5-客户端简要描述

nonolog起步笔记-5-客户端简要描述 客户端的简要的设计图路notify模式服务端最好分两个核 NanoLog::setLogLevel(NOTICE);从 NANO_LOG 开始NANO_LOGcompiling time的语句getNumNibblesNeeded&#xff1a;得到prompt中&#xff0c;number的数量countFmtParams&#xff1a;得到所…...

Flink:入门介绍

目录 一、Flink简介 2.1 Flink 架构 2.2 Flink 应用程序 运行模式 二、Flink 集群 部署 2.1 本地集群模式 2.1.1 安装JDK​编辑 2.1.2 下载、解压 Flink 2.1.3 启动集群 2.1.4 停止集群 2.2 Standalone 模式 2.2.0 集群规划 2.2.1 安装JDK 2.2.2 设置免密登录 2…...

目标跟踪领域经典论文解析

亲爱的小伙伴们&#x1f618;&#xff0c;在求知的漫漫旅途中&#xff0c;若你对深度学习的奥秘、JAVA 、PYTHON与SAP 的奇妙世界&#xff0c;亦或是读研论文的撰写攻略有所探寻&#x1f9d0;&#xff0c;那不妨给我一个小小的关注吧&#x1f970;。我会精心筹备&#xff0c;在…...

网络编程 | TCP套接字通信及编程实现经验教程

1、TCP基础铺垫 TCP/IP协议簇中包含了如TCP、UDP、IP、ICMP、ARP、HTTP等通信协议。TCP协议是TCP/IP协议簇中最为常见且重要的通信方式之一&#xff0c;它为互联网上的数据传输提供了可靠性和连接管理。 TCP&#xff08;Transmission Control Protocol&#xff0c;传输控制协议…...

SAP导出表结构并保存到Excel 源码程序

SAP导出表结构并保存到Excel,方便写代码时复制粘贴 经常做接口,需要copy表结构,找到了这样一个程程,特别有用。 01. 先看结果...

Linux下redis环境的搭建

1.redis的下载 redis官网下载redis的linux压缩包&#xff0c;官网地址:Redis下载 网盘链接&#xff1a; 通过网盘分享的文件&#xff1a;redis-5.0.4.tar.gz 链接: https://pan.baidu.com/s/1cz3ifYrDcHWZXmT1fNzBrQ?pwdehgj 提取码: ehgj 2.redis安装与配置 将包上传到 /…...

REDMI瞄准游戏赛道,推出小屏平板

近日&#xff0c;REDMI推出了一款8.8英寸的小屏平板&#xff0c;引发市场关注。该平板采用LCD屏幕&#xff0c;搭载天玑9400处理器&#xff0c;定位游戏市场&#xff0c;意在开拓小屏平板的新领域‌。 ‌小屏平板新尝试‌ 这款REDMI平板未追随大屏潮流&#xff0c;而是选择了8…...

springai结合ollama

目录 ollama 介绍 使用 下载&#xff1a; 安装&#xff1a; 点击这个玩意next就行了。 运行 spring ai使用ollama调用本地部署的大模型 加依赖 配置yml 写代码 ollama 介绍 官网&#xff1a;Ollama Ollama是一个用于部署和运行各种开源大模型的工具&#xff1b; …...

React第十三节开发中常见问题之(视图更新、事件处理)

一、视图更新有哪些方案&#xff1f; useState用法介绍 1、对于数据变量 正常的增删改查&#xff0c;只会让数据更新&#xff0c;但是不会触发 React 视图的更新&#xff1b; 如&#xff1a; <script lang"jsx">const baseTable [{name:Andy, age: 18, id…...

【Appium报错】安装uiautomator2失败

目录 1、通过nmp安装uiautomator2&#xff1a;失败 2、通过 Appium 的平台直接安装驱动程序 3、通过pip 来安装 uiautomator2 1、通过nmp安装uiautomator2&#xff1a;失败 我先是通过npm安装的uiautomator2&#xff0c;也显示已经安装成功了&#xff1a; npm install -g …...

DataSophon集成CMAK KafkaManager

本次集成基于DDP1.2.1 集成CMAK-3.0.0.6 设计的json和tar包我放网盘了. 通过网盘分享的文件&#xff1a;DDP集成CMAK 链接: https://pan.baidu.com/s/1BR70Ajj9FxvjBlsOX4Ivhw?pwdcpmc 提取码: cpmc CMAK github上提供了zip压缩包.将压缩包解压之后 在根目录下加入启动脚本…...

Ubuntu22.04深度学习环境安装【显卡驱动安装】

前言 使用Windows配置环境失败&#xff0c;其中有一个包只有Linux版本&#xff0c;Windows版本的只有python3.10的&#xff0c;所以直接选用Linux来配置环境&#xff0c;显卡安装比较麻烦&#xff0c;单独出一期。 显卡驱动安装 方法一&#xff1a;在线安装&#xff08;操作…...

21届秋/校招面经

开篇先说一下我自身情况&#xff0c;东南大学本科计算机科学与技术专业毕业&#xff0c;gpa3.2/4.8。零零散散搞过一年多ACM&#xff0c;去年&#xff08;2019&#xff09;在icpc上海站拿了铜之后增加了信心&#xff08;因为当时训练总时间半年不到&#xff09;&#xff0c;于是…...

相机动态/在线标定

图1 图2 基本原理 【原理1】平行线在射影变换后会交于一点。如图所示,A为相机光心,蓝色矩形框为归一化平面,O为平面中心。地面四条黄色直线为平行且等距的车道线。HI交其中两条车道线于H、I, 过G作HI的平行线GM交车道线于M。HI、GM在归一化平面上的投影分别为JK、PN,二者会…...

MySQL 8.0 新特性汇总

文章目录 前言1. 运维管理 1.1 可持久化变量1.2 管理员端口1.3 资源组1.4 数据库粒度只读1.5 show processlist 实现方式1.6 加速索引创建速度1.7 控制连接的内存使用量1.8 克隆插件1.9 mysqldump 新增参数1.10 慢日志增强1.11 快速加列1.12 InnoDB 隐藏主键1.13 Redo 配置1.14…...

Resnet C ++ 部署 tensort 部署(四)

Resnet C 部署 pytorch功能测试&#xff08;一&#xff09; Resnet C 部署 模型训练&#xff08;二&#xff09; Resnet C 部署 模型测试&转 onnx&#xff08;三&#xff09; Resnet C 部署 tensort 部署&#xff08;四&#xff09; 之后&#xff0c;开始onnx 转trt 部…...

《Java核心技术I》对并发散列映射的批操作

对并发散列映射的批操作 Java API提供了批处理&#xff0c;计时其他线程处理映射&#xff0c;这些操作也能安全的执行。 3种不同操作&#xff1a; search(搜索)&#xff0c;为每个键或值应用一个函数&#xff0c;直到函数生成一个非null的结果&#xff0c;然后搜索终止&…...

记录一次使用git无权限的问题排查

正常的配置了公私钥之后&#xff0c;在gitlab中也存储了配对的公钥&#xff0c;但当使用git clone 时&#xff0c;总是报无权限 由于在这台机器中添加了多个公私钥&#xff0c;有点复杂&#xff0c;我们可以使用命令 ssh -vvvT 调试一下 ssh -vvvT yourGitlabAddr...

appium学习之二:adb命令

1、查看设备 adb devices 2、连接 adb connect IP:端口 3、安装 adb install xxx.apk 4、卸载 adb uninstall 【包名】 5、把对应目录下的1.txt文件传到手机sdcard下 adb push 1.txt /sdcard 6、进入对应的设备里 adb shell 7、切入sdcard目录 cd /sdcard 8、ls 查…...

ESP32读取DHT11温湿度数据

芯片&#xff1a;ESP32 环境&#xff1a;Arduino 一、安装DHT11传感器库 红框的库&#xff0c;别安装错了 二、代码 注意&#xff0c;DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现

摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序&#xff0c;以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务&#xff0c;提供稳定高效的数据处理与业务逻辑支持&#xff1b;利用 uniapp 实现跨平台前…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

04-初识css

一、css样式引入 1.1.内部样式 <div style"width: 100px;"></div>1.2.外部样式 1.2.1.外部样式1 <style>.aa {width: 100px;} </style> <div class"aa"></div>1.2.2.外部样式2 <!-- rel内表面引入的是style样…...

ArcGIS Pro制作水平横向图例+多级标注

今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作&#xff1a;ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等&#xff08;ArcGIS出图图例8大技巧&#xff09;&#xff0c;那这次我们看看ArcGIS Pro如何更加快捷的操作。…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列&#xff0c;以便知晓哪些列包含有价值的数据&#xff0c;…...

Redis的发布订阅模式与专业的 MQ(如 Kafka, RabbitMQ)相比,优缺点是什么?适用于哪些场景?

Redis 的发布订阅&#xff08;Pub/Sub&#xff09;模式与专业的 MQ&#xff08;Message Queue&#xff09;如 Kafka、RabbitMQ 进行比较&#xff0c;核心的权衡点在于&#xff1a;简单与速度 vs. 可靠与功能。 下面我们详细展开对比。 Redis Pub/Sub 的核心特点 它是一个发后…...

Java编程之桥接模式

定义 桥接模式&#xff08;Bridge Pattern&#xff09;属于结构型设计模式&#xff0c;它的核心意图是将抽象部分与实现部分分离&#xff0c;使它们可以独立地变化。这种模式通过组合关系来替代继承关系&#xff0c;从而降低了抽象和实现这两个可变维度之间的耦合度。 用例子…...