React和Redux中的不变性
https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/
一、不变性和副作用
1.不变:不断创造新值来替换旧值
2.不变性规则:
(1)当给定相同的输入时,纯函数必须始终返回相同的值
(2)纯函数不能有任何副作用
3.副作用:修改直接函数范围之外的东西
改变/修改传入的参数(的属性)
修改函数外部的任何其他状态,例如全局变量
进行API调用
console.log()
Math.random()
4.会改变数组的数组方法:push,pop,shift,unshift,sort,reverse,splic
如果想对数组进行不可变的操作,可以先复制该数组,再对副本进行操作
5.纯函数只能调用其他纯函数
二、React更喜欢不变性
1.不变性和PureComponent
继承了React.Component的function和class类型的react组件会在父级组件重新渲染或者使用setState时重新渲染。
继承了React.PureComponent的class仅在其状态更新或者其props更新时才会重新渲染。
将props传入到PureComponent中时,需要保证不可变的更新,因为如果直接修改内部或者属性,但是引用不变,则组件无法注意到它已经改变,则不会重新渲染。
2.JS中的引用相等性
对象和数组存储在内存中,当重新分配变量时,变量会指向新的内存地址,但如果仅改变变量的内部结构,变量仍指向相同的地址,地址里面的内容发生变化。
使用===比较对象和数组时,本质是在比较引用地址,即“引用相等”。
修改一个对象时,会修改对象的内容,但不会更改其引用。将一个对象分配给另一个对象时,指向相同的内存位置,对第二个对象的操作也会影响第一个对象的值。
为什么不深入检查是否相等:速度慢,时间复杂度O(N)
比较引用:O(1),不管对象内部有多复杂
3.const只阻止重新分配引用, 不阻止改变对象内容
4.思考:React框架从性能方面考虑,为了保证复杂场景下的性能,在比较的时候没有挨个比较object内部的值,而是比较引用地址,保证每次比较的时间复杂度都是O(1)。因此从这个设计思想出发,在更新State的时候,都是基于旧值返回新值(引用地址改变),而不是直接通过object.属性=xxx来直接修改object的内容。所以大部分语言修改一个object的属性的时候是通过object.属性=xxx来修改,React是基于旧值返回新值。
三、在Redux中更新state(主要内容,前面都是为了解释这个)
1.要求reducers是纯函数,不能直接修改state:接受state和action,基于旧的state,返回一个新的state。上面的部分解释了可变和不可变,下面介绍了,如何不可变的更新state
- 对象扩展运算符…:创建包含与另一个对象或数组完全相同的内容的新对象或数组
3.更新state:会浅合并传入的this.setState()对象
在redux的reducer中:
(1)更新普通的state
return {
…state,
(updates here)
}
(2)更新对象最顶层的属性时,需要复制现有的state,通过…展开对象,然后加入想要更改的属性及其值
function reducer(state, action) {
/*
State looks like:
state = {clicks: 0,count: 0
}
*/
return {
…state,
clicks: state.clicks + 1,
count: state.count - 1
}
}
(3)更新对象中的对象,当想要更新的部分位于深层时,需要把每一级展开并创建副本
function reducer(state, action) {
/*
State looks like:
state = {house: {name: "Ravenclaw",points: 17}
}
*/
// Two points for Ravenclaw
return {
…state, // copy the state (level 0)
house: {
…state.house, // copy the nested object (level 1)
points: state.house.points + 2
}
}
(4)通过key来更新对象
function reducer(state, action) {
/*
State looks like:
const state = {houses: {gryffindor: {points: 15},ravenclaw: {points: 18},hufflepuff: {points: 7},slytherin: {points: 5}}
}
*/
// Add 3 points to Ravenclaw,
// when the name is stored in a variable
const key = “ravenclaw”;
return {
…state, // copy state
houses: {
…state.houses, // copy houses
[key]: { // update one specific house (using Computed Property syntax)
…state.houses[key], // copy that specific house’s properties
points: state.houses[key].points + 3 // update its points
property
}
}
}
(5)将一个Item添加到数组中
通过Array.prototype.unshift和push将Item添加到数组前面/后面会改变数组,希望通过不可变的方式添加Item(对象展开复制,或者通过.slice复制后再push)
function reducer(state, action) {
/*
State looks like:
state = [1, 2, 3];
*/
const newItem = 0;
return [ // a new array
newItem, // add the new item first
…state // then explode the old state at the end 添加到前面
];
return [ // a new array
newItem, // add the new item first
…state // then explode the old state at the end 添加到后面
];
//或者通过.slice复制数组,在push到末尾
function reducer(state, action) {
const newItem = 0;
const newState = state.slice();
newState.push(newItem);
return newState;
(6)通过map更新数组中的item
通过.map来遍历每个item,找到要修改的item,使用返回值作为这个item新的值,最后map返回一个新的数组,需要筛选则使用.filter
function reducer(state, action) {
/*
State looks like:
state = [1, 2, "X", 4];
*/
return state.map((item, index) => {
// Replace “X” with 3
// alternatively: you could look for a specific index
if(item === “X”) {
return 3;
}
// Leave every other item unchanged
return item;
});
}
(7)更新数组中的对象
通过.map遍历每个item,找到要修改的对象,复制这个对象并对副本进行修改,作为一个新的对象返回,最后map返回一个新的数组,需要筛选则使用.filter
function reducer(state, action) {
/*
State looks like:
state = [{id: 1,email: 'jen@reynholmindustries.com'},{id: 2,email: 'peter@initech.com'}
]Action contains the new info:action = {type: "UPDATE_EMAIL"payload: {userId: 2, // Peter's IDnewEmail: 'peter@construction.co'}
}
*/
//通过map返回的是一个新的数组
return state.map((item, index) => {
// Find the item with the matching id
if(item.id === action.payload.userId) {
// Return a new object 修改后,返回的是一个新对象
return {
…item, // copy the existing item 复制这个对象不需要修改的部分
email: action.payload.newEmail // replace the email addr
}
}
// Leave every other item unchanged
return item;
});
}
(8)在数组中间插入一个item
.splice函数将插入一个item,但会改变数组。可以先试用slice复制数组,再使用splice插入item,或者复制新item之前的元素,插入新item,再复制item之后的元素
function reducer(state, action) {
/*
State looks like:
state = [1, 2, 3, 5, 6];
*/
const newItem = 4;
// make a copy
const newState = state.slice();
// insert the new item at index 3
newState.splice(3, 0, newItem)
return newState;
/*
// You can also do it this way:
return [ // make a new array
…state.slice(0, 3), // copy the first 3 items unchanged
newItem, // insert the new item
…state.slice(3) // copy the rest, starting at index 3
];
*/
}
(9)按索引更新数组中的item
使用map找到这个item并返回新值
function reducer(state, action) {
/*
State looks like:
state = [1, 2, "X", 4];
*/
return state.map((item, index) => {
// Replace the item at index 2
if(index === 2) {
return 3;
}
// Leave every other item unchanged
return item;
});
}
(10)从数组中删除一个item
通过filter,传入每个item,返回一个只包含判断函数返回true的item的新数组
function reducer(state, action) {
/*
State looks like:
state = [1, 2, "X", 4];
*/
return state.filter((item, index) => {
// Remove item “X”
// alternatively: you could look for a specific index
if(item === “X”) {
return false;
}
// Every other item stays
return true;
});
}
相关文章:
React和Redux中的不变性
https://overreacted.io/zh-hans/a-complete-guide-to-useeffect/ 一、不变性和副作用 1.不变:不断创造新值来替换旧值 2.不变性规则: (1)当给定相同的输入时,纯函数必须始终返回相同的值 (2࿰…...

NPM 常用命令(一)
目录 1、npm 1.1 简介 1.2 依赖性 1.3 安装方式 2、npm access 2.1 命令描述 2.2 详情 3、npm adduser 3.1 描述 4、npm audit 4.1 简介 4.2 审计签名 4.3 操作示例 4.4 配置 audit-level dry-run force json package-lock-only omit foreground-scripts …...
【ES6】Promise推荐用法
一般来说,不要在then()方法里面定义 Reject 状态的回调函数(即then的第二个参数),总是使用catch方法。 // bad promise.then(function(data) {// success}, function(err) {// error});// good promise.then(function(data) { //…...
【JavaScript】版本判断
用于客户端和服务端进行版本更新判断使用,如有BUG,还望指出 效果 console.log(isAllowUpdate(1,2.0.0), // trueisAllowUpdate(2.0,2.0.0), // falseisAllowUpdate(2.0,2.0.1), // trueisAllowUpdate(2.1.1,2.1.2), // trueisAllowUpdate(2.1.3,2.1.2),…...

Nano编辑器安装使用指南
关于nano Nano编辑器是一个命令行文本编辑器,具有简单易用的界面和一些基本功能。 Nano小巧友好,提供许多额外的特性,例如交互式的查找和替换、定位到指定的行列、自动缩进、特性切换、国际化支持、文件名标记完成等。 Nano是为了代替闭源的…...

Java版电子招投标管理系统源码-电子招投标认证服务平台-权威认证
项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范,以及…...

Java String类(1)
String类的重要性 我们之前在C语言中已经涉及到字符串了,但是在C语言中要表示字符串只能使用字符数组或者字符指针,可以使用标准库提供的字符串系列函数完成大部分操作,但是这种将数据和操作数据的方法分离开的方式不符合面向对象的思想&…...

渗透测试漏洞原理之---【CSRF跨站请求伪造】
文章目录 1、CSRF概述1.1、基本原理1.1.1、基本概念1.1.2、关键点1.1.3、目标 1.2、CSRF场景1.2.1、银行支付转账1.2.2构造虚假网站1.2.3、场景建模 1.3、CSRF类别1.3.1、POST方式 1.4、CSRF验证1.4.1、CSRF PoC Generator 2、CSRF攻防2.1、CSRF实战2.1.1、与XSS 漏洞相结合 2.…...

带量采购药品数据查询集采分析平台(建议收藏!)
药品集采常态化下对不同中标企业的影响不尽相同,对于市场份额较大且拥有多款重要药品的大型企业来说,集采能够保持其市场份额,尽管被集采的药品可能会面临销售下降的局面,但该企业还有其他产品可以填补,整体影响不大。…...

概念解析 | 无线感知的新篇章:异构网络感知的原理与挑战
注1:本文系“概念解析”系列之一,致力于简洁清晰地解释、辨析复杂而专业的概念。本次辨析的概念是:异构网络感知。 无线感知的新篇章:异构网络感知的原理与挑战 Interference Management in HetNets 在当今的无线通信领域,我们面临着一个重大的挑战:如何在有限的频谱资源…...

【大数据模型】让chatgpt为开发增速(开发专用提示词)
汝之观览,吾之幸也!本文主要聊聊怎样才能更好的使用提示词,给开发提速,大大缩减我们的开发时间,比如在开发中使用生成表结构脚本的提示词,生成代码的提示词等等。 一、准备 本文主要根据Claude进行演示&am…...

读书笔记-《ON JAVA 中文版》-摘要23[第二十章 泛型-2]
文章目录 第二十章 泛型5. 泛型擦除5.1 泛型擦除5.2 迁移兼容性5.3 擦除的问题5.4 边界处的动作 6. 补偿擦除7. 边界8. 通配符8.1 通配符8.2 逆变 9. 问题10. 动态类型安全11. 泛型异常 第二十章 泛型 普通的类和方法只能使用特定的类型:基本数据类型或类类型。如果…...

【爬虫】5.6 Selenium等待HTML元素
目录 任务目标 创建Ajax网站 创建服务器程序 Selenium XX 等待 1. Selenium强制等待 2. Selenium隐性等待 3. Selenium循环等待 4. Selenium显示等待 等待方法 任务目标 在浏览器加载网页的过程中,网页的有些元素时常会有延迟的现象,在HTML元素…...

0102阿里云配置3台ECS服务器-大数据学习
文章目录 1 前言1 配置VPC和子网2 创建安全组3 创建云服务器ECS3.1 规划配置3.2 配置 4 xshell连接服务器5 配置基础环境5.1 主机名映射5.2 ssh免密登录5.3 jdk 6 问题集6.1 Permission denied (publickey,gssapi-keyex,gssapi-with-mic).6.2 用tar解压文件出现错误Not found i…...

android 输入法demo
背景: 一个简单的android输入法demo,支持输入png、gif,jpeg、webp等格式。 此示例演示如何编写一个应用程序,该应用程序接受使用 Commit Content API 从键盘发送的丰富内容(例如图像)。 用户通常希望通过表…...

【经验分享】Markdown中如何显示空格和回车
Markdown中如何显示空格和回车 空格 利用html中的空格实体引用: eg: 这是一些 额外的空格。回车: 方法一:在你想要回车的地方连续按两次回车键 方法二:使用<br>标签 eg: 我想显示<br>…...

深入篇【C++】set和map(multiset/multimap)特性总结与使用
深入篇【C】set和map(multiset/multimap)特性总结与使用 一.set/multiset总结二.map/multiset总结三.set/map应用 一.set/multiset总结 set是按照一定次序存储元素的容器在set中,元素的value也标识它(value就是key,类型为T),并且每…...

OpenAI推出ChatGPT企业版,提供更高安全和隐私保障
🦉 AI新闻 🚀 OpenAI推出ChatGPT企业版,提供更高安全和隐私保障 摘要:OpenAI发布了面向企业用户的ChatGPT企业版,用户可以无限制地访问强大的GPT-4模型,进行更深入的数据分析,并且拥有完全控制…...

Linux虚拟机磁盘扩容
Linux虚拟机磁盘扩容 问题起源 在使用linux系统开发时遇到文件无法创建的问题,根据提示发现是磁盘空间不足。 使用df -h查看具体磁盘使用情况。 针对这个问题,有两种解决方案: 使用du -sh ./*可以查看当前工作目录下各文件的占用空间大小…...

【Go 基础篇】Go语言结构体实例的创建详解
在Go语言中,结构体是一种强大的数据类型,允许我们定义自己的复杂数据结构。通过结构体,我们可以将不同类型的数据字段组合成一个单一的实例,从而更好地组织和管理数据。然而,在创建结构体实例时,有一些注意…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)
题目:3442. 奇偶频次间的最大差值 I 思路 :哈希,时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况,哈希表这里用数组即可实现。 C版本: class Solution { public:int maxDifference(string s) {int a[26]…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...

关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
聊一聊接口测试的意义有哪些?
目录 一、隔离性 & 早期测试 二、保障系统集成质量 三、验证业务逻辑的核心层 四、提升测试效率与覆盖度 五、系统稳定性的守护者 六、驱动团队协作与契约管理 七、性能与扩展性的前置评估 八、持续交付的核心支撑 接口测试的意义可以从四个维度展开,首…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
Go语言多线程问题
打印零与奇偶数(leetcode 1116) 方法1:使用互斥锁和条件变量 package mainimport ("fmt""sync" )type ZeroEvenOdd struct {n intzeroMutex sync.MutexevenMutex sync.MutexoddMutex sync.Mutexcurrent int…...

【 java 虚拟机知识 第一篇 】
目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...

篇章二 论坛系统——系统设计
目录 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 1. 数据库设计 1.1 数据库名: forum db 1.2 表的设计 1.3 编写SQL 2.系统设计 2.1 技术选型 2.2 设计数据库结构 2.2.1 数据库实体 通过需求分析获得概念类并结合业务实现过程中的技术需要&#x…...