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(一) createAsyncThunk(二) 性能优化 createSelector 异步逻辑 //Product.js const onAdd () > {const name nameRef.current.value// 触发添加商品的事件dispatch(addProduct({name…...
Halcon WPF 开发学习笔记(3):WPF+Halcon初步开发
文章目录 前言在MainWindow.xaml里面导入Halcon命名空间WPF简单调用Halcon创建矩形简单调用导出脚本函数 正确显示匹配效果 前言 本章会简单讲解如何调用Halcon组件和接口,因为我们是进行混合开发模式。即核心脚本在平台调试,辅助脚本C#直接调用。 在M…...
P6入门:项目初始化9-项目详情之资源 Resource
前言 使用项目详细信息查看和编辑有关所选项目的详细信息,在项目创建完成后,初始化项目是一项非常重要的工作,涉及需要设置的内容包括项目名,ID,责任人,日历,预算,资金,分类码等等&…...
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 下载地址:MySQL Installer。 我们下载最新版本(目前是8.0.35)的安装包,注意要选择更大的那个,名字为 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创建表关系 如何创建表关系(一对一 , 一对多 , 多对多) 图书表,出版社表,作者表,作者详情表 换位思考法判断表关系 图书表和出版社表 >>> 一对多 >>> 图书表是多,出…...
MongoDB副本集配置和创建
副本集有三类角色:master(primary),slave(secondary),仲裁服务器。 primary是主,只有primary能写入,secondary无法插入数据,且需要声明是slave才能查看数据 一般生产搞三个服务器做一个master和两个slave&a…...
使用 `open-uri.with_proxy` 方法打开网页
Ruby 爬虫程序如下: 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 范式有哪些? 2.3 第一范式(1NF) 2.4 第二范式(2NF) 2.5 第三范式(3NF) 2.6 小结 1. 设计数据表需要注意的点 (1)首先要考虑设计这张表的用途,这张表都要存放什…...
Brute Force
Brute Force "Brute Force"(暴力破解)指的是一种通过尝试所有可能的组合来获取访问、解密或破解信息的攻击方法。这种攻击方法通常是基于暴力和不断尝试的,不依赖漏洞或弱点。通常用于破解密码、破坏系统或获取未经授权的访问权限…...
HTML简单介绍
且视他人之疑目如盏盏鬼火,大胆地去你的夜路。 目录 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 井字棋 链接:井字棋 题目: 给定一个二维数组board,代表棋盘,其中元素为1的代表是当前玩家的棋子,0表示没有棋子,-1代表是对方玩家的棋子。当一方棋子在横竖斜方向上有连成排的及获胜(及…...
C语言求数组中出现次数最多的元素
一、前言 遇到一个需求,需要求数组中出现次数最多的元素,查找了一些资料,结合自己的思路,编写了程序并验证。 只考虑元素为非负整数的数组,如果有出现次数相同的元素,则返回较小元素。 二、编程思路 以数…...
【Python Opencv】Opencv画图形
文章目录 前言一、画图形1.1 画线1.2 画矩形1.3 画圆1.4 画椭圆1.5 添加文本 总结 前言 在计算机视觉和图像处理中,OpenCV不仅可以处理图像和视频,还提供了一组功能强大的工具,用于在图像上绘制各种形状和图形。这些功能使得我们能够在图像上…...
了解防抖和节流:提升前端交互体验的实用策略
了解防抖和节流:提升前端交互体验的实用策略 前言什么是防抖?什么是节流?应用实例防抖实例节流实例 前言 本文将重点介绍前端性能优化方法之一的防抖和节流。首先解释了它们的概念和原理,然后探讨了它们在前端开发中的应用场景&a…...
SQL学习之增删改查
文章目录 数据库数据类型建表create table插入数据insert into查询数据select from修改数据update set删除数据delete from备份ctas结果插入iis截断表 truncate table修改表结构alter table添加注释 注:本文的SQL语法是基于Oracle数据库操作的,但是基本的…...
Ansible角色定制实例
目录 角色定制:roles 角色定制实例:利用角色部署wordpress 1.在roles目录下生成对应的目录结构 2.定义配置文件 ①nginx ②php ③mysql ④定义剧本文件 ⑤启动服务 角色定制:roles 对于普通的剧本(playbook)有…...
ElastaticSearch--- es多字段聚合
在使用es时,我们经常会用到聚合查询。 简单的聚合查询,已经在前面介绍过,详情见: https://www.cnblogs.com/expiator/p/13843969.html 有时,也会用到多字段聚合查询。类似于Mysql的Group By多个字段。 比如…...
本周Github有趣开源项目:Rspress等6个
Github有趣的项目、工具和库: 1、sshx 一个基于 Web 的安全协作终端。通过网络进行快速、协作的实时终端共享 特征: 运行一个命令即可与任何人共享您的终端。 在无限画布上调整大小、移动窗口以及自由缩放和平移。 查看其他人的光标实时移动。 连接到…...
label-studio的使用教程(导入本地路径)
文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...
vue3 字体颜色设置的多种方式
在Vue 3中设置字体颜色可以通过多种方式实现,这取决于你是想在组件内部直接设置,还是在CSS/SCSS/LESS等样式文件中定义。以下是几种常见的方法: 1. 内联样式 你可以直接在模板中使用style绑定来设置字体颜色。 <template><div :s…...
c#开发AI模型对话
AI模型 前面已经介绍了一般AI模型本地部署,直接调用现成的模型数据。这里主要讲述讲接口集成到我们自己的程序中使用方式。 微软提供了ML.NET来开发和使用AI模型,但是目前国内可能使用不多,至少实践例子很少看见。开发训练模型就不介绍了&am…...
有限自动机到正规文法转换器v1.0
1 项目简介 这是一个功能强大的有限自动机(Finite Automaton, FA)到正规文法(Regular Grammar)转换器,它配备了一个直观且完整的图形用户界面,使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
嵌入式常见 CPU 架构
架构类型架构厂商芯片厂商典型芯片特点与应用场景PICRISC (8/16 位)MicrochipMicrochipPIC16F877A、PIC18F4550简化指令集,单周期执行;低功耗、CIP 独立外设;用于家电、小电机控制、安防面板等嵌入式场景8051CISC (8 位)Intel(原始…...
提升移动端网页调试效率:WebDebugX 与常见工具组合实践
在日常移动端开发中,网页调试始终是一个高频但又极具挑战的环节。尤其在面对 iOS 与 Android 的混合技术栈、各种设备差异化行为时,开发者迫切需要一套高效、可靠且跨平台的调试方案。过去,我们或多或少使用过 Chrome DevTools、Remote Debug…...
Xela矩阵三轴触觉传感器的工作原理解析与应用场景
Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知,帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量,能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度,还为机器人、医疗设备和制造业的智…...
简约商务通用宣传年终总结12套PPT模版分享
IOS风格企业宣传PPT模版,年终工作总结PPT模版,简约精致扁平化商务通用动画PPT模版,素雅商务PPT模版 简约商务通用宣传年终总结12套PPT模版分享:商务通用年终总结类PPT模版https://pan.quark.cn/s/ece1e252d7df...

