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

React【异步逻辑createAsyncThunk(一)、createAsyncThunk(二)、性能优化、createSelector】(十二)

文章目录

异步逻辑

createAsyncThunk(一)

createAsyncThunk(二)

性能优化

createSelector


异步逻辑

//Product.js
const onAdd = () => {const name = nameRef.current.value// 触发添加商品的事件dispatch(addProduct({name}))
}

如果要让异步逻辑与Store交互,我们需要使用redux middleware。
Redux 有多种异步 middleware,每一种都允许你使用不同的语法编写逻辑。最常见的异步 middleware 是 redux-thunk ,它可以让你编写可能直接包含异步逻辑的普通函数。
Redux Toolkit 的 configureStore 功能默认自动设置 thunk middleware,我们推荐使用 thunk 作为 Redux 开发异步逻辑的标准方式。


Thunk 函数
在Thunk函数中我们可以编写异步逻辑的代码(例如 setTimeout 、Promise 和 async/await ),并且可以通过参数获取到dispatch,getState()。从而在异步操作执行后再diapacth action。
 

提示:
Thunk 通常写在 “slice” 文件中。

//slices/productSlice.js
import { createSlice } from '@reduxjs/toolkit'
//定义初始state
//list表示商品列表,isLoading表示是否为正在请求数据的状态
const initialState = { list: [] ,isLoading:false}
//创建slice
const slice = createSlice({//定义域名称name: 'product',//传入初始stateinitialState,//定义reducersreducers: {//这个reducer用来把商品数据存储到store中addProduct: (state, action) => {state.list.push(action.payload)},//这个reducer用来更改isLoadingchangeState:(state,action)=>{state.isLoading=action.payload}}
})
//导出action creator
export const { addProduct ,changeState} = slice.actions
//导出thunk函数
//addProductAsync为thunk函数的创建函数,它返回一个thunk函数
//返回的thunk函数中我们就可以编写异步代码了
export const addProductAsync = (payload) => (dispatch, getState) => {//触发action ,改变isLoading的状态dispatch(changeState(true))setTimeout(() => {dispatch(addProduct(payload))//触发action ,改变isLoading的状态dispatch(changeState(false))}, 3000)
}//导出reducer
export default slice.reducer
//pages/Product.js
import React, { useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux'
import { addProductAsync } from '../slices/productSlice'
//引入thunk函数
export default function Product() {const nameRef = useRef()const {list:productList,isLoading} = useSelector(state => state.product)const dispatch = useDispatch()const onAdd = () => {//thunk函数的使用,跟普通的action creator的使用一样dispatch(addProductAsync({ name: nameRef.current.value }))}return (<div>我是商品页面<br />商品名:<input ref={nameRef} required /><br />{isLoading?<div>请求数据中... </div>:productList.map((item, index) => <li key={index}>商品名:{item.name}</li>)}<button onClick={onAdd}>新增商品</button></div>);
}

createAsyncThunk(一)

 Redux Toolkit 的 createAsyncThunk API 生成 thunk,为你自动 dispatch 那些 "状态" action。

 createAsyncThunk 接收 2 个参数:
1、 参数一:将用作生成的 action type的前缀的字符串
2 、一个 “payload creator” 回调函数,它应该返回一个 Promise 或者其他数据

 //slices/productSlice.js
//使用createAsyncThunk创建thunk
//接收的第一个参数是action 的 type的前缀
//第二个参数是一个函数,用来返回payload
export const addProductPost = createAsyncThunk('product/addProductPost', (item)=>{return  new Promise((resolve,reject)=>{setTimeout(()=>{resolve(item)},3000)})
})

提示:
当调用 dispatch(addProductPost()) 的时候, addProductPost 这个 thunk 会
首先 dispatch 一个 action 类型为 'product/addProductPost/pending'
当异步代码执行完,返回的Promise resove后会dispatch 一个
action 类型为 product/addProductPost/fulfilled

 在组件中 dispatch thunk

import React, { useRef } from 'react';
import { useSelector, useDispatch } from 'react-redux'
import { addProductPost } from '../slices/productSlice'
//引入thunk函数
export default function Product() {const nameRef = useRef()const {list:productList,isLoading} = useSelector(state => state.product)const dispatch = useDispatch()const onAdd = () => {//thunk函数的使用,跟普通的action creator的使用一样dispatch(addProductPost({ name: nameRef.current.value }))}return (<div>我是商品页面<br />商品名:<input ref={nameRef} required /><br />{isLoading?<div>请求数据中...</div>:productList.map((item, index) => <li key={index}>商品名:{item.name}</li>)}<button onClick={onAdd}>新增商品</button></div>);}

添加extraReducers
extraReducers可以监听createAsyncThunk创建的action被 dispatch。
 

//slices/productSlice.js
//创建slice
const slice = createSlice({//定义域名称name: 'product',//传入初始stateinitialState,//定义reducersreducers: {//这个reducer用来把商品数据存储到store中addProduct: (state, action) => {state.list.push(action.payload)},//这个reducer用来更改isLoadingchangeState:(state,action)=>{state.isLoading=action.payload}},//extraReducer设置createAsyncThunk创建的thunk被dispatch后的reducer处理器extraReducers(builder){builder.addCase(addProductPost.pending,(state,action)=>{state.isLoading=true}).addCase(addProductPost.fulfilled,(state,action)=>{state.isLoading=falsestate.list.push(action.payload)})}
})

createAsyncThunk(二)

 提示:
createAsyncThunk 自动生成 pending/fulfilled/rejected action 类型

//slices/productSlice.js
//创建获取商品数据的thunk
export const productListGet = createAsyncThunk('product/productListGet',
async () => {const data = await new Promise((resolve, reject) => {setTimeout(() => {resolve([{ name: '苹果' }, {name: '香蕉' }, { name: "蓝莓" }])}, 3000)})return data
})
extraReducers(builder) {builder.addCase(addProductPost.pending,(state, action) => {state.isLoading = true}).addCase(addProductPost.fulfilled, (state,action) => {state.isLoading = falsestate.list.push(action.payload)}).addCase(productListGet.pending, (state, action) => {state.isLoading = true}).addCase(productListGet.fulfilled, (state, action) => {return { list: action.payload, isLoading: false }}).addCase(productListGet.rejected, (state,action) => {state.isLoading=false})}
//pages/Product.js
import { addProductPost, productListGet } from '../slices/productSlice'
//组件挂载后请求商品数据
useEffect(() => {dispatch(productListGet())}, [])

提示:
Immer 让我们以两种方式更新状态:要么 更新 现有状态值,要么 return 一个新结果。
如果我们返回一个新值,它将用我们返回的任何内容完全替换现有状态。

性能优化

 React.memo()
React 的默认行为是当父组件渲染时,React 会递归渲染其中的所有子组件!

//pages/ProductChild.js
import React, { useEffect } from 'react';
function ProductChild() {useEffect(() => {console.log('子元素重新渲染')})return (<div>子元素</div>);
}
export default React.memo(ProductChild)

为了让子组件跳过没有必要的渲染,我们可以将 子组件包装在 React.memo() 中,这可以确保组件只有在 props 真正更改时才会重新渲染。
 

//pages/ProductChild.js
export default React.memo(ProductChild)

createSelector

 如果子组件中使用了useSelector来获取数据,也会存在一些不必要的渲染。

 提示:

一般情况下,只要我们dispatch 了 action,store发生了变更之后,那么传递给useSelector的选择器器就会被重新调用,如果选择器返回的结果跟原来的状态不一样,则组件重新被渲染。

import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
function ProductChild() {const list=useSelector(state=>state.product.list.filter(item=>item.name.length>2))useEffect(() => {console.log('子元素重新渲染')})return (<div>子元素</div>);
}
export default React.memo(ProductChild)

我们可以使用 createSelector 来定义有记忆的选择器。
 

//slices/productSlice.js
import { createSelector} from '@reduxjs/toolkit'
export const selectList= createSelector([state =>{    return state.product.list
} ], (list) => {console.log('重新计算list')return list.filter(item=>item.name.length>2)
})

createSelector函数可以接收N-1个输入函数,一个输出函数(最终的选择器),前面的N-1个输入函数的参数由调用输出函数的时候传入的参数决定,输出函数的参数由前面N-1个输入函数的返回值决定。只有当输出函数的参数发生了变更,输出函数才会被重新执行。

//pages/ProductChild.js
import React, { useEffect } from 'react';
import { useSelector } from 'react-redux';
import {selectList} from '../slices/productSlice'
function ProductChild() {// const list=useSelector(state=>state.product.list.filter(item=>item.name.length>2))const list=useSelector(selectList)useEffect(() => {console.log('子元素重新渲染')})return (<div>子元素</div>);
}
export default React.memo(ProductChild)

相关文章:

React【异步逻辑createAsyncThunk(一)、createAsyncThunk(二)、性能优化、createSelector】(十二)

文章目录 异步逻辑 createAsyncThunk&#xff08;一&#xff09; createAsyncThunk&#xff08;二&#xff09; 性能优化 createSelector 异步逻辑 //Product.js const onAdd () > {const name nameRef.current.value// 触发添加商品的事件dispatch(addProduct({name…...

Halcon WPF 开发学习笔记(3):WPF+Halcon初步开发

文章目录 前言在MainWindow.xaml里面导入Halcon命名空间WPF简单调用Halcon创建矩形简单调用导出脚本函数 正确显示匹配效果 前言 本章会简单讲解如何调用Halcon组件和接口&#xff0c;因为我们是进行混合开发模式。即核心脚本在平台调试&#xff0c;辅助脚本C#直接调用。 在M…...

P6入门:项目初始化9-项目详情之资源 Resource

前言 使用项目详细信息查看和编辑有关所选项目的详细信息&#xff0c;在项目创建完成后&#xff0c;初始化项目是一项非常重要的工作&#xff0c;涉及需要设置的内容包括项目名&#xff0c;ID,责任人&#xff0c;日历&#xff0c;预算&#xff0c;资金&#xff0c;分类码等等&…...

Python高级语法----使用Python进行模式匹配与元组解包

文章目录 1. 模式匹配的新特性2. 高级元组解包技巧3. 数据类的匹配与应用1. 模式匹配的新特性 Python自3.10版本起引入了结构化模式匹配的新特性,这是一种强大的工具,允许开发者用更清晰、更直观的方式处理数据结构。模式匹配类似于其他编程语言中的switch-case语句,但它更…...

MySQL安装配置与使用教程(2023.11.13 MySQL8.0.35)

CONTENTS 1. MySQL的安装与配置2. MySQL常用操作教程 1. MySQL的安装与配置 MySQL Windows Installer 下载地址&#xff1a;MySQL Installer。 我们下载最新版本&#xff08;目前是8.0.35&#xff09;的安装包&#xff0c;注意要选择更大的那个&#xff0c;名字为 mysql-inst…...

【阿里云数据采集】采集标准Docker容器日志:部署阿里云Logtail容器以及创建Logtail配置,用于采集标准Docker容器日志

文章目录 引言I 预备知识1.1 Logtail1.2 安装Logtail1.3 创建用户自定义标识机器组1.4 设置logtail容器组件重启策略II 采集服务器日志2.1 采集同一账号下同地域服务器的日志2.2 不同账号下同地域服务器的日志2.3 创建Logtail配置III 查询语法3.1 具体查询语法3.2 查询示例3.3 …...

Django中如何创建表关系,请求生命周期流程图

Django中ORM创建表关系 如何创建表关系(一对一 &#xff0c; 一对多 &#xff0c; 多对多) 图书表&#xff0c;出版社表&#xff0c;作者表&#xff0c;作者详情表 换位思考法判断表关系 图书表和出版社表 >>> 一对多 >>> 图书表是多&#xff0c;出…...

MongoDB副本集配置和创建

副本集有三类角色&#xff1a;master(primary)&#xff0c;slave(secondary)&#xff0c;仲裁服务器。 primary是主&#xff0c;只有primary能写入&#xff0c;secondary无法插入数据&#xff0c;且需要声明是slave才能查看数据 一般生产搞三个服务器做一个master和两个slave&a…...

使用 `open-uri.with_proxy` 方法打开网页

Ruby 爬虫程序如下&#xff1a; require open-uri require nokogiri# 定义代理信息 proxy_host jshk.com.cn# 定义要爬取的网页 URL url http://www.example.com# 使用代理信息打开网页 open-uri.with_proxy(proxy_host, proxy_port) do |proxy|# 使用 Nokogiri 库解析网页内…...

数据库表的设计——范式

目录 1. 设计数据表需要注意的点 2. 范式 2.1 范式简介 2.2 范式有哪些&#xff1f; 2.3 第一范式(1NF) 2.4 第二范式(2NF) 2.5 第三范式(3NF) 2.6 小结 1. 设计数据表需要注意的点 &#xff08;1&#xff09;首先要考虑设计这张表的用途&#xff0c;这张表都要存放什…...

Brute Force

Brute Force "Brute Force"&#xff08;暴力破解&#xff09;指的是一种通过尝试所有可能的组合来获取访问、解密或破解信息的攻击方法。这种攻击方法通常是基于暴力和不断尝试的&#xff0c;不依赖漏洞或弱点。通常用于破解密码、破坏系统或获取未经授权的访问权限…...

HTML简单介绍

且视他人之疑目如盏盏鬼火&#xff0c;大胆地去你的夜路。 目录 1.网页 2.Web标准 3.HTML 3.1HTML结构 3.2HTML标签​编辑 4.标签介绍 4.1排版标签 4.2文本格式化标签 4.3媒体标签 4.3.1图片标签 4.3.2 音频标签 4.3.3视频标签 5.相对路径 6.链接标签 6.1target属…...

【Java笔试强训】Day10(CM62 井字棋、HJ87 密码强度等级)

CM62 井字棋 链接&#xff1a;井字棋 题目&#xff1a; 给定一个二维数组board&#xff0c;代表棋盘&#xff0c;其中元素为1的代表是当前玩家的棋子&#xff0c;0表示没有棋子&#xff0c;-1代表是对方玩家的棋子。当一方棋子在横竖斜方向上有连成排的及获胜&#xff08;及…...

C语言求数组中出现次数最多的元素

一、前言 遇到一个需求&#xff0c;需要求数组中出现次数最多的元素&#xff0c;查找了一些资料&#xff0c;结合自己的思路&#xff0c;编写了程序并验证。 只考虑元素为非负整数的数组&#xff0c;如果有出现次数相同的元素&#xff0c;则返回较小元素。 二、编程思路 以数…...

【Python Opencv】Opencv画图形

文章目录 前言一、画图形1.1 画线1.2 画矩形1.3 画圆1.4 画椭圆1.5 添加文本 总结 前言 在计算机视觉和图像处理中&#xff0c;OpenCV不仅可以处理图像和视频&#xff0c;还提供了一组功能强大的工具&#xff0c;用于在图像上绘制各种形状和图形。这些功能使得我们能够在图像上…...

了解防抖和节流:提升前端交互体验的实用策略

了解防抖和节流&#xff1a;提升前端交互体验的实用策略 前言什么是防抖&#xff1f;什么是节流&#xff1f;应用实例防抖实例节流实例 前言 本文将重点介绍前端性能优化方法之一的防抖和节流。首先解释了它们的概念和原理&#xff0c;然后探讨了它们在前端开发中的应用场景&a…...

SQL学习之增删改查

文章目录 数据库数据类型建表create table插入数据insert into查询数据select from修改数据update set删除数据delete from备份ctas结果插入iis截断表 truncate table修改表结构alter table添加注释 注&#xff1a;本文的SQL语法是基于Oracle数据库操作的&#xff0c;但是基本的…...

Ansible角色定制实例

目录 角色定制&#xff1a;roles 角色定制实例&#xff1a;利用角色部署wordpress 1.在roles目录下生成对应的目录结构 2.定义配置文件 ①nginx ②php ③mysql ④定义剧本文件 ⑤启动服务 角色定制&#xff1a;roles 对于普通的剧本&#xff08;playbook&#xff09;有…...

ElastaticSearch--- es多字段聚合

在使用es时&#xff0c;我们经常会用到聚合查询。 简单的聚合查询&#xff0c;已经在前面介绍过&#xff0c;详情见&#xff1a; https://www.cnblogs.com/expiator/p/13843969.html 有时&#xff0c;也会用到多字段聚合查询。类似于Mysql的Group By多个字段。 比如&#xf…...

本周Github有趣开源项目:Rspress等6个

Github有趣的项目、工具和库&#xff1a; 1、sshx 一个基于 Web 的安全协作终端。通过网络进行快速、协作的实时终端共享 特征&#xff1a; 运行一个命令即可与任何人共享您的终端。 在无限画布上调整大小、移动窗口以及自由缩放和平移。 查看其他人的光标实时移动。 连接到…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

Docker 离线安装指南

参考文章 1、确认操作系统类型及内核版本 Docker依赖于Linux内核的一些特性&#xff0c;不同版本的Docker对内核版本有不同要求。例如&#xff0c;Docker 17.06及之后的版本通常需要Linux内核3.10及以上版本&#xff0c;Docker17.09及更高版本对应Linux内核4.9.x及更高版本。…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

python/java环境配置

环境变量放一起 python&#xff1a; 1.首先下载Python Python下载地址&#xff1a;Download Python | Python.org downloads ---windows -- 64 2.安装Python 下面两个&#xff0c;然后自定义&#xff0c;全选 可以把前4个选上 3.环境配置 1&#xff09;搜高级系统设置 2…...

STM32+rt-thread判断是否联网

一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序

一、开发准备 ​​环境搭建​​&#xff1a; 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 ​​项目创建​​&#xff1a; File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)

在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

大数据学习(132)-HIve数据分析

​​​​&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...