React和Redux中的不变性

这篇具有很好参考价值的文章主要介绍了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

  1. 对象扩展运算符…:创建包含与另一个对象或数组完全相同的内容的新对象或数组

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 ID
    newEmail: '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;

});
}文章来源地址https://www.toymoban.com/news/detail-689723.html

到了这里,关于React和Redux中的不变性的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • React中使用Redux (二) - 通过react-redux库连接React和Redux

    react-redux库使用Redux 上一篇文章演示React中直接使用Redux的使用过程是十分繁琐的, 并且有许多重复代码 但是实际上redux官方帮助我们提供了 react-redux 的库,这个库是帮助我们完成连接redux和react的辅助工具, 可以直接在项目中使用,并且实现的逻辑会更加的严谨和高效 这篇我们

    2024年02月20日
    浏览(53)
  • 【React】redux和React-redux

    🎀个人主页:努力学习前端知识的小羊 感谢你们的支持:收藏🎄 点赞🍬 加关注🪐 redux 适用于多交互、多数据源的场景。 使用redux的场景: 某个组件的状态需要共享 一个组件需要改变其他组件的状态时 一个组件需要改变全局的状态时 redux的三大原则: 整个应用的 state

    2024年02月06日
    浏览(56)
  • React中使用Redux (一) - 在React中直接使用Redux

    开始之前需要强调一下,redux和react没有直接的关系,你完全可以在React, Angular, Ember, jQuery, or vanilla JavaScript中使用Redux 。 尽管这样说,redux依然是和React库结合的更好,因为他们是通过state函数来描述界面的状态,Redux可以发射状态的更新, 让他们作出相应; 目前redux在react中使

    2024年01月23日
    浏览(59)
  • 在react中使用redux && react-redux的使用demo

    前言: redux是一种状态管理工具,可以存储和操作一些全局或者很多组件需要使用的公共数据。 平心而论,redux的使用对于新上手来说不太友好,多个依赖包的,多种api的结合使用,相对来说比做同样一件事的vuex用起来比较麻烦.不过,熟能生巧,用多了也就习惯了,下面是个人的一个d

    2024年02月06日
    浏览(54)
  • 【React】React——redux

    🚩🚩🚩 💎个人主页: 阿选不出来 💨💨💨 💎个人简介: 一名大二在校生,学习方向前端,不定时更新自己学习道路上的一些笔记. 💨💨💨 💎目前开发的专栏: JS 🍭Vue🍭React🍭 💨💨💨 Redux 是 JavaScript 状态容器,提供可预测化的状态管理。 redux是什么 redux是一个专门用于

    2024年01月15日
    浏览(47)
  • 什么是redux?如何在react 项目中使用redux?

    redux是一种用于管理JavaScript应用程序的状态管理库。它可以与React、Augular、Vue等前端框架结合使用,但也可以纯在JavaScript应用程序中独立使用。redux遵循单项数据流的原则,通过一个全局的状态树来管理应用程序的状态,从而使状态的变化更加可预测和已于维护。 redux的核心

    2024年02月15日
    浏览(38)
  • 【React】React中编写CSS,Redux

    ❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: style接受一个采用小驼峰命名属性的JS对象,而不是CSS字符串,可以动态获取当前state中的状态 缺点:1.写法上面需要使用驼峰2.编写样式没有提示3.大量的样式,代码混乱4

    2024年02月09日
    浏览(37)
  • React笔记(八)Redux

    一、安装和配置 React 官方并没有提供对应的状态机插件,因此,我们需要下载第三方的状态机插件 —— Redux。 1、下载Redux 在终端中定位到项目根目录,然后执行以下命令下载 Redux 2、创建配置文件 在 React 中,不会自动生成状态机的相关配置代码,因此,需要我们自己手动

    2024年02月10日
    浏览(39)
  • React | 再战Redux

    ✨ 个人主页:CoderHing 🖥️ React.js专栏:React.js 再战Redux 🙋‍♂️ 个人简介:一个不甘平庸的平凡人🍬 💫 系列专栏:吊打面试官系列  16天学会Vue  7天学会微信小程序  Node专栏 🍀 格言: ☀️ 路漫漫其修远兮,吾将上下而求索☀️ 👉 你的一键三连是我更新的最大动力!

    2024年02月12日
    浏览(47)
  • React中使用Redux

            redux是一个专门用于状态管理的一个库,和vue中的vuex功能类似。其中核心点就是状态的管理。虽然我们无论在vue还是在react中我们组件间的通行都可以使用消息总线或者父子组件间的消息传递来进行操作。但是如果我们需要A组件的状态在其他十个或者二十个组件上进

    2024年02月16日
    浏览(47)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包