【React】状态管理

两个状态管理工具:

  1. dva 是一个基于 Redux 和 React Router 的数据流方案,它提供了对 Redux 和 React Router 的封装,使得在使用 dva 时可以更方便地进行状态管理和路由操作。
  2. React Redux是一个JavaScript状态管理库,它的核心包括store、action和reducer。store负责存储和管理状态,action描述状态变化,reducer则根据旧状态和action计算新状态。

简单来说,

  • useState可以直接更新状态;
  • useReducer通过dispatch多个action来更新状态,reducer函数脱离了UI,可以独立复用;
  • useSelector负责从store全局中读取和渲染状态,useDispatch负责通过分发action,更新store状态,二者都存在于React-Redux中;
  • connect是存在于dva中,负责从store中读取状态,并传递给组件。

目录

useState

useReducer

useSelector、useDispatch

connect


正文

  • useState

 直接更新状态。

  • useReducer

 可以脱离了UI,可以独立复用。但无法像redux一样进行跨组件的状态共享。

对于拥有许多状态更新逻辑的组件来说,过于分散的事件处理程序可能会令人不知所措。对于这种情况,你可以将组件的所有状态更新逻辑整合到一个外部函数中,这个函数叫作 reducer。

使用 reducer 管理状态与直接设置状态略有不同。它不是通过设置状态来告诉 React “要做什么”,而是通过事件处理程序 dispatch 一个 “action” 来指明 “用户刚刚做了什么”。(而状态更新逻辑则保存在其他地方!)

function handleAddTask(text) {
// "action" 对象:dispatch({type: 'added',id: nextId++,text: text,});
}function handleChangeTask(task) {dispatch({type: 'changed',task: task,});
}function handleDeleteTask(taskId) {dispatch({type: 'deleted',id: taskId,});
}

“action”是一个普通的 JavaScript 对象。它的结构是由你决定的,在后面的步骤中,你将会学习如何添加一个 dispatch 函数。

reducer 函数就是你放置状态逻辑的地方。它接受两个参数,分别为当前 state 和 action 对象,并且返回的是更新后的 state,如下(在 reducer 中使用 switch 语句 是一种惯例):

function tasksReducer(tasks, action) {switch (action.type) {case 'added': {return [...tasks,{id: action.id,text: action.text,done: false,},];}case 'changed': {return tasks.map((t) => {if (t.id === action.task.id) {return action.task;} else {return t;}});}case 'deleted': {return tasks.filter((t) => t.id !== action.id);}default: {throw Error('未知 action: ' + action.type);}}
}

最后,在组件中导入taskReducer

import { useState } from 'react';
⬇️
import { useReducer } from 'react';const [tasks, setTasks] = useState(initialTasks);
⬇️
const [tasks, dispatch] = useReducer(tasksReducer, initialTasks);
  • useSelector、useDispatch

useSelector、useDispatch都是react-redux里面的

用法:首先通过reducer给state赋值num

const reducer = (state, action) => {switch (action.type) {case "decrement":return { ...state, num: state.num - 1 };case "increment":return { ...state, num: state.num + 1 };default:return state;}
}

先通过createStore将state存入redux store

const store = createStore(reducer, initialState);

接着通过provider把state传给子组件

const ComponentUseReactRedux = () => {return (<div><h2>ComponentUseReactRedux</h2><Provider store={store}><ChildComponentUseReactRedux /></Provider></div>)
}

最后在子组件里,useSelector负责读取和渲染状态,useDispatch负责触发状态更新

  • 通过useSelector(选择器函数)从store全局状态里提取需要的部分,这里是state里的num。当 dispatch(action) 触发 reducer 修改状态后,Store 会通知所有订阅的组件。
  • useSelector 会比较 上一次选择器返回值 和 新返回值: 如果不同(!==),组件重新渲染。 如果相同,组件不会重新渲染(避免不必要的更新)。
  • useDispatch通过distpatch触发状态更新,dispatch(action) 是 Redux 中触发状态更新的唯一方式
const ChildComponentUseReactRedux = () => {const num = useSelector(state => state.num);const dispatch = useDispatch();return (<div><h3>Using useSelector, useDispatch</h3>Number: {num}//组件调用,dispatch(action),store传递state和action//reducer会根据action计算新状态,store更新状态并通知组件<button onClick={() => dispatch({ type: "increment" })}>+</button><button onClick={() => dispatch({ type: "decrement" })}>-</button></div>);
}

  • connect

/**
* 简单写法
* 将state.products 映射到组件的 props.products
* connect 是一个高阶函数,它接收两个可选参数 mapStateToProps 和 mapDispatchToProps,并返回一个高阶组件
*/
export default connect(({ products }) => ({products,
}))(Products);/**
* 更规范的写法
* 这样 Products 组件就可以通过 this.props.products 访问到 Redux store 中的 products 数据
* 这种情况没有用到mapDispatchToProps,不需要派发actions
*/
const mapStateToProps = (state) => {return {products: state.products,};
};export default connect(mapStateToProps)(Products);/**
* 需要派发action的情况
* mapDispatchToProps 用于将 Action Creator 绑定到组件的 props,这样组件就可以直接调用它们来派发 Action
*/
import { fetchProducts } from './actions';const mapDispatchToProps = {fetchProducts, // 将 action creator 映射到 props
};export default connect((state) => ({ products: state.products }),mapDispatchToProps
)(Products);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/94267.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/94267.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

⭐CVPR2025 FreeUV:无真值 3D 人脸纹理重建框架

&#x1f4c4;论文题目&#xff1a;FreeUV: Ground-Truth-Free Realistic Facial UV Texture Recovery via Cross-Assembly Inference Strategy ✍️作者及机构&#xff1a;Xingchao Yang、Takafumi Taketomi、Yuki Endo、Yoshihiro Kanamori&#xff08;CyberAgent、Universit…

Google Chrome <140.0.7297.0 MediaStreamTrackImpl UAF漏洞

【高危】Google Chrome <140.0.7297.0 MediaStreamTrackImpl UAF漏洞 漏洞描述 Google Chrome 是美国谷歌&#xff08;Google&#xff09;公司的一款Web浏览器。 受影响版本中&#xff0c;当处理媒体流时&#xff0c;MediaStreamTrackImpl 组件在销毁前&#xff0c;未能清…

在VSCode中定制C语言宏格式化

在编写C语言代码时,经常会遇到一些宏定义的问题,特别是当使用宏来简化变量声明时。假设你有一个宏定义如下: #define VAR(vartype, memclass) vartype VAR(float32, AUTOMATIC) var1; // 等同于 "float32 var1;"当你使用VSCode的Format Document</

LangChain4J入门:使用SpringBoot-start

这是连续的专栏内容 &#xff08;一&#xff09;提换依赖 将原有的 <!-- LangChain4j OpenAI 集成 --><dependency><groupId>dev.langchain4j</groupId><artifactId>langchain4j-open-ai</artifactId></dependency> 换成 <!…

AR-Align-NN-2024

文章目录An unsupervised multi-view contrastive learning framework with attention-based reranking strategy for entity alignment摘要1. 引言2. 相关工作2.1. 实体对齐2.2 对比学习中的数据增强3. 问题定义4. 方法论4.1 嵌入初始化4.2 图谱数据增强4.3 多视图对比学习4.4…

DeFi借贷协议深度解析:原理与Python实现

目录 DeFi借贷协议深度解析:原理与Python实现 1. DeFi借贷协议概述 2. 核心数学原理 2.1 抵押率计算 2.2 健康因子 2.3 利率模型 3. 协议核心组件 3.1 资金池架构 3.2 状态变量 4. 核心功能实现 4.1 存款功能 4.2 借款功能 4.3 利息计算与更新 5. 清算机制实现 5.1 清算逻辑 5…

信创及一次ORACLE到OB的信创迁移

信创及一次ORACLE到OB的信创迁移 1.信创是什么? 2.银行信创要求:核心目标与挑战 3.一次ORACLE到OceanBase(OB)的信创迁移方案 3.0.目标: 3.1.迁移评估OceanBase Migration Assessment (OMA) 3.2.数据对象迁移 3.3.数据迁移 3.4.OceanBase 导数工具 3.5.调用存储过程跑批 3…

[Python] -进阶理解10- 用 Python 实现简易爬虫框架

网络爬虫是自动抓取网页并提取数据的程序。本篇文章将基于 Python,从请求、解析和数据流控制三个核心模块出发,逐步构建一个简易爬虫框架,并辅以代码示例与扩展建议,适合初学者快速掌握爬虫架构设计。 一、爬虫架构总览 典型爬虫框架包含以下模块流程: Seed URLs:初始化…

oracle备库主机断电重启后IO异常报错

两节点rac adg环境4个实例&#xff0c;节点1异常重启后IO报错 检查控制文件为0字节&#xff0c;第一感觉是不是控制文件损坏了&#xff1f;但节点2说是没有报错&#xff0c;理论上如果控制文件坏了&#xff0c;库应该挂掉了。 尝试重启另外一共adg实例&#xff0c;发现读取其它…

简单线性回归模型原理推导(最小二乘法)和案例解析

线性回归是一种用于建模自变量与因变量之间线性关系的统计方法&#xff0c;核心是通过最小化误差平方和估计模型参数。以下从数学原理推导和案例两方面详细说明。 一、线性回归模型的数学原理推导 1. 模型定义 线性回归假设因变量 y 与自变量 x 存在线性关系&#xff0c;具体…

主成分分析法 PCA 是什么

主成分分析法 PCA 是什么 主成分分析法(Principal Component Analysis,简称PCA)是一种数据降维与特征提取方法,核心思想是通过线性变换将高维数据映射到低维空间,在尽可能保留原始数据“信息量”(即方差)的同时,减少数据维度,消除特征间的相关性。 主成分分析法(PC…

Elasticsearch太重?试试轻量、极速的Meilisearch

在构建现代化的应用时&#xff0c;“搜索”早已不再是锦上添花的功能&#xff0c;而是决定用户留存体验的关键一环。Meilisearch&#xff0c;作为一款专为速度、易用性与开发者体验而生的开源搜索引擎&#xff0c;正受到越来越多开发者的青睐。 本文将介绍 Meilisearch 的核心…

车载通信架构 ---车内通信的汽车网络安全

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 做到欲望极简,了解自己的真实欲望,不受外在潮流的影响,不盲从,不跟风。把自己的精力全部用在自己。一是去掉多余,凡事找规律,基础是诚信;二是…

MySQL: with as与with RECURSIVE如何混合使用?

文章目录一、with用法系列文章二、前言三、MySQL 普通CTE与递归CTE混合使用的严格规则四、解决方案4.1、方法1&#xff1a;嵌套查询4.2、方法2&#xff1a;使用临时表4.3、方法3&#xff1a;分开执行&#xff08;应用层处理&#xff09;本文主要探讨mysql中with普通cte与递归ct…

腕管综合征 : “鼠标手”| “数字时代工伤”,在我国视频终端工作者中患病率达12%到15%。“

文章目录 引言 I 预防“鼠标手” 肌腱的滑动 正中神经的滑动 II “鼠标手”是怎么发生的? 症状 “鼠标手”的高发人群 引言 “鼠标手”发展到晚期会对神经造成不可逆的损伤。 早期刚开始有症状,比如说轻微的麻木,持续的时间也不长,发作频率也不高的情况下,我们可以通过像…

#C语言——刷题攻略:牛客编程入门训练(三):输出格式化、基本运算符

&#x1f31f;菜鸟主页&#xff1a;晨非辰的主页 &#x1f440;学习专栏&#xff1a;《C语言刷题合集》 &#x1f4aa;学习阶段&#xff1a;C语言方向初学者 ⏳名言欣赏&#xff1a;"代码行数决定你的下限&#xff0c;算法思维决定你的上限。" 目录 1. 牛牛的空格分…

【ELasticsearch】集群故障模拟方案(二):磁盘空间满、重选主节点

《集群故障模拟方案》系列&#xff0c;共包含以下文章&#xff1a; 1️⃣ 集群故障模拟方案&#xff08;一&#xff09;&#xff1a;节点宕机、节点离线2️⃣ 集群故障模拟方案&#xff08;二&#xff09;&#xff1a;磁盘空间满、重选主节点 &#x1f60a; 如果您觉得这篇文章…

React中的Hooks

在React 16.8版本之前&#xff0c;组件主要分为两种&#xff1a;类组件&#xff08;Class Components&#xff09; 和 函数组件&#xff08;Function Components&#xff09;。类组件可以使用 state 来管理内部状态&#xff0c;也能使用生命周期方法&#xff08;如 componentDi…

【21】C# 窗体应用WinForm ——图片框PictureBox属性、方法、实例应用

文章目录12. 图片框PictureBox12.2 PictureBox插入、删除图片12.2.1 插入方式一&#xff1a;右键导入12.2.2 插入方式二&#xff1a;程序路径读入12.2.3 删除图片&#xff1a;右键清除12.3 实例&#xff1a;一键实现图片交换12.4 图片与窗口尺寸——SizeMode属性——实例对比1 …

Vue-Router 4.0:新一代前端路由管理

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》、《前端求职突破计划》 &#x1f35a; 蓝桥云课签约作者、…