当前位置: 首页 > 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 查…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

VTK如何让部分单位不可见

最近遇到一个需求&#xff0c;需要让一个vtkDataSet中的部分单元不可见&#xff0c;查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行&#xff0c;是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示&#xff0c;主要是最后一个参数&#xff0c;透明度…...

高防服务器能够抵御哪些网络攻击呢?

高防服务器作为一种有着高度防御能力的服务器&#xff0c;可以帮助网站应对分布式拒绝服务攻击&#xff0c;有效识别和清理一些恶意的网络流量&#xff0c;为用户提供安全且稳定的网络环境&#xff0c;那么&#xff0c;高防服务器一般都可以抵御哪些网络攻击呢&#xff1f;下面…...

StarRocks 全面向量化执行引擎深度解析

StarRocks 全面向量化执行引擎深度解析 StarRocks 的向量化执行引擎是其高性能的核心设计&#xff0c;相比传统行式处理引擎&#xff08;如MySQL&#xff09;&#xff0c;性能可提升 5-10倍。以下是分层拆解&#xff1a; 1. 向量化 vs 传统行式处理 维度行式处理向量化处理数…...

spring boot使用HttpServletResponse实现sse后端流式输出消息

1.以前只是看过SSE的相关文章&#xff0c;没有具体实践&#xff0c;这次接入AI大模型使用到了流式输出&#xff0c;涉及到给前端流式返回&#xff0c;所以记录一下。 2.resp要设置为text/event-stream resp.setContentType("text/event-stream"); resp.setCharacter…...

Nginx 事件驱动理解

在做埋点采集服务的过程中&#xff0c;主要依靠openresty加lua脚本来实现采集。高并发还是主要依靠nginx来实现。而其核心就是事件驱动/多路io复用&#xff08;epoll机制&#xff09;&#xff0c;不同的linux服务器都有对应的实现方式。 而epoll机制就是&#xff0c;应用启动的…...

STM32CubeMX-H7-19-ESP8266通信(中)--单片机控制ESP8266实现TCP地址通信

前言 上篇文章我们已经能够使用串口助手实现esp8266的几种通信&#xff0c;接下来我们使用单片机控制实现。这篇文章会附带教程&#xff0c;增加.c和,.h&#xff0c;把串口和定时器放到对应的编号&#xff0c;然后调用初始化就可以使用了。 先讲解&#xff0c;然后末尾再放源码…...

【web笔记】JavaScript实现有动画效果的进度条

文章目录 1 实现效果2 实现代码 1 实现效果 2 实现代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"utf-8"><style>#progress {width: 300px;height: 20px;border-radius: 0; /* 移除圆角 */-webkit-appearance…...

Flask与Celery 项目应用(shared_task使用)

目录 1. 项目概述主要功能技术栈 2. 项目结构3. 环境设置创建虚拟环境并安装依赖主要依赖 4. 应用配置Flask应用初始化 (__init__.py)Celery应用初始化 (make_celery.py) 5. 定义Celery任务 (tasks.py)任务说明 6. 创建API端点 (views.py)API端点说明 7. 前端界面 (index.html)…...

【从零学习JVM|第二篇】字节码文件

前言&#xff1a; 通过了解字节码文件可以帮助我们更容易的理解JVM的工作原理&#xff0c;所以接下来&#xff0c;我们来介绍一下字节码文件。 目录 前言&#xff1a; 正确的打开字节码文件 字节码文件组成 1. 魔数&#xff08;Magic Number&#xff09; 2. 版本号&…...