我的编程空间,编程开发者的网络收藏夹
学习永远不晚

详解React setState数据更新机制

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

详解React setState数据更新机制

为什么使用setState

在React 的开发过程中,难免会与组件的state打交道。使用过React 的都知道,想要修改state中的值,必须使用内部提供的setState 方法。为什么不能直接使用赋值的方式修改state的值呢?我们就分析一下,先看一个demo。


class Index extends React.Component {
  this.state = {
    count: 0
  }
  onClick = () => {
    this.setState({
       count: 10
    })
  }
  render() {
    return (
      <div>
        <span>{this.state.count}</span>
        <button onClick={this.onClick}>click</button>
      </div>
    )
  }
}

根据上面代码可以看到,点击按钮后把state 中 count 的值修改为 10。并更新页面的显示。所以state的改变有两个作用:对应的值改变 和 **页面更新。**要想做到这两点在react 中 非 setState 不可。 假如说我们把 onClick 的方法内容修改为 this.state.count = 10 并在方法内打印出 this.state 的值,可以看到state的值已经改变。但是页面并没有更新到最新的值。 ☆总结一下:

  • state 值的改变,目的是页面的更新,希望React 使用最新的 state来渲染页面。但是直接赋值的方式并不能让React监听到state的变化。
  • 必须通过setState 方法来告诉React state的数据已经变化。

☆扩展一下:

在vue中,采用的就是直接赋值的方式来更新data 数据,并且Vue也能够使用最新的data数据渲染页面。这是为什么呢? 在vue2中采用的是 Object.defineProperty() 方式监听数据的get 和 set 方法,做到数据变化的监听 在vue3中采用的是ES6 的 proxy 方式监听数据的变化

setState 的用法

想必所有人都会知道setState 的用法,在这里还是想记录一下: setState方法有两个参数:第一个参数可以是对象直接修改属性值,也可以是函数能够拿到上一次的state值。第二个参数是一个可选的回调函数,可以获取最新的state值 回调函数会在组件更新完成之后执行,等价于在 componentDidUpdate 生命周期内执行。

  • 第一个参数是对象时:如同上文的demo一样,直接修改state的属性值

this.setState({
	key:newState
})
  • 第一个参数是函数时:在函数内可以获取上一次state 的属性值。

// prevState 是上一次的 state,props 是此次更新被应用时的 props
this.setState((prevState, props) => {
  return {
      key: prevState.key 
  }
})

异步更新还是同步更新

setState() 将对组件 state 的更改排入队列,并通知 React 需要使用更新后的 state 重新渲染此组件及其子组件。这是用于更新用户界面以响应事件处理器和处理服务器数据的主要方式 将 setState() 视为请求而不是立即更新组件的命令。为了更好的感知性能,React 会延迟调用它,然后通过一次传递更新多个组件。React 并不会保证 state 的变更会立即生效。

先修改一下上面的代码,如果在onClick 方法中连续调用三次setState,根据上文可知 setState是一个异步的方式,每次调用只是将更改加入队列,同步调用的时候只会执行最后一次更新,所以结果是1而不是3。


onClick = () => {
  const { count } = this.state
  this.setState({ count: count + 1 })
  this.setState({ count: count + 1 })
  this.setState({ count: count + 1 })
}

可以把上面代码理解为 Object.assign() 方法,


Object.assign(
  state,
  { count: state.count + 1 },
  { count: state.count + 1 },
  { count: state.count + 1 }
)

如果第一个参数传入一个函数,连续调用三次,是不是和传入对象方式的结果是一样的呢?


onClick = () => {
  this.setState((prevState, props) => {
    return {
      count: prevState.count + 1
    }
  })
  this.setState((prevState, props) => {
    return {
      count: prevState.count + 1
    }
  })
  this.setState((prevState, props) => {
    return {
      count: prevState.count + 1
    }
  })
}

结果和传入对象的方式大相径庭,使用函数的方式就能够实现自增为3的效果。这又是为什么呢? 在函数内能够拿到最新的state 和 props值。由上文可知 setState 的更新是分批次的,使用函数的方式确保了当前state 是建立在上一个state 之上的,所以实现了自增3的效果。

☆总结一下: 为什么setState 方法是异步的呢?

  • 可以显著的提升性能,react16 引入了 Fiber 架构,Fiber 中对任务进行了划分和优先级的分类,优先处理优先级比较高的任务。页面的响应就是一个优先级比较高任务,所以如果setState是同步,那么更新一次就要更新一次页面,就会阻塞到页面的响应。最好的办法就是获得到多个更新,之后进行批量的更新。只更新一次页面。
  • 如果同步更新state,但是还没有执行render 函数,那么state 和 props 就不能够保持同步。

**是不是所有的setState 都是异步的形式呢?**答案是 否!!!在React 中也会存在setState 同步的场景


onClick = () => {
	this.setState({ count: this.state.count + 1 })
  console.log(this.state)
  setTimeout(() => {
    this.setState({ count: this.state.count + 1 })
    console.log(this.state)
  }, 0)
}

上面的代码会打印出**0,2。**这又是为什么呢?其实React 中的 setState 并不是严格意义上的异步函数。他是通过队列的延迟执行实现的。使用 isBatchingUpdates 判断当前的setState 是加入到更新队列还是更新页面。当 isBatchingUpdates=ture 是加入更新队列,否则执行更新。

知道了React 是使用 isBatchingUpdates 来判断是否加入更新队列。那么为什么在 setTimeout 事件中 isBatchingUpdates 值为 false ? 原因就是在React中,对HTML的原生事件做了一次封装叫做**合成事件。**所以在React自己的生命周期和合成事件中,可以控制 isBatchingUdates 的值,可以根据值来判断是否更新页面。而在宿主环境提供的原生事件中(即非合成事件),无法将 isBatchingUpdates 的值置为 false,所以就会立即执行更新。

☆所以setState 并不是有同步的场景,而是在特殊的场景下不受React 的控制 **

总结

setState 并不是单纯的同步函数或者异步函数,他的同步和异步的表现差异体现在调用的场景不同。在React 的生命周期和合成事件中他表现为异步函数。而在DOM的原生事件等非合成事件中表现为同步函数。

以上就是详解React setState数据更新机制的详细内容,更多关于React setState数据更新机制的资料请关注编程网其它相关文章!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

详解React setState数据更新机制

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

React状态更新的优先级机制源码解析

这篇文章主要为大家介绍了React状态更新的优先级机制源码解析,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

VuenextTick延迟回调获取更新后DOM机制详解

这篇文章主要为大家介绍了VuenextTick延迟回调获取更新后DOM机制详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

MySQL实现数据更新的示例详解

目录一、方法分类二、具体用法(1)根据条件更新值(2)按照不同条件(批量)更新不同值三、实例(1)根据条件更新值(2)按照不同条件更新不同值一般在更新时会遇到以下场景:1.所有字段全部更新;2.根据条件更新字段中的某部分内容;3.根据
2023-02-08

MySQL学习之数据更新操作详解

目录UPDATE 语句UPDATE 语句练习①UPDATE 语句练习②UPDATE 语句练习③UPDATE 语句的表连接UPDATE 语句练习④UPDATE 语句UPDATE 语句用于修改表的记录,语法如下UPDATE IGNORE 表
2022-08-08

MySQL实现数据批量更新功能详解

最近需要批量更新大量数据,习惯了写sql,所以还是用sql来实现,下面这篇文章主要给大家总结介绍了关于MySQL批量更新的方式,需要的朋友可以参考下
2023-02-11

深入详解java高并发热点数据更新

这篇文章主要为大家深入介绍了java高并发热点数据更新详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-05-18

SQL更新与删除数据操作示例详解

目录1、更新数据2、根据其他表更新数据3、删除数据4、根据其他表删除数据对于不加WHERE条件的UPDATE和DELETE要格外谨慎!1、更新数据1.1 更新全部数据:android使用UPDATE关键字。语法如下:UPDATE 表名
2023-01-05

Android数据持久化之Preferences机制详解

本文实例讲述了Android数据持久化之Preferences机制。分享给大家供大家参考,具体如下:在Android中,实现数据持久化有五种方式:Preferences,文件File,I/O操作、SQLite数据库,ContentProvi
2023-05-31

阿里云数据库更新的操作方法详解

简介:阿里云数据库是阿里云提供的一种云端数据库服务,它具有高可用性、高性能、高安全性等特点,被广泛应用于各种互联网应用中。在使用阿里云数据库的过程中,有时候需要对数据库进行更新操作,本文将详细介绍如何进行阿里云数据库的更新操作。在进行阿里云数据库更新之前,我们需要先了解一些基本概念。首先,数据库是指存储数据的仓库,它可
阿里云数据库更新的操作方法详解
2023-12-26

详解vue表格更新页面怎么同步数据

Vue是一种流行的JavaScript框架,已被广泛应用于前端开发中。在开发过程中,我们通常需要使用表格来展示数据。当数据发生更新时,我们希望页面能够同步更新,以保证用户体验。那么在Vue中,表格如何实现数据的同步更新呢?一、Vue的响应式机制Vue的核心思想是响应式编程,即当数据发生变化时,页面会自动更新。Vue利用了ES6中的Object.defineProperty方法,
2023-05-14

详解MySQL的数据行和行溢出机制

一、行 有哪些格式? 你可以像下面这样看一下你的MySQL行格式设置。其实MySQL的数据行有两种格式,一种就是图中的 Compact格式,还有一种是Redundant格式。 Compact是一种紧凑的行格式,设计的初衷就是为了让一个数据页
2022-05-10

vue的异步数据更新机制与$nextTick使用方法是什么

这篇文章主要讲解了“vue的异步数据更新机制与$nextTick使用方法是什么”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“vue的异步数据更新机制与$nextTick使用方法是什么”吧!v
2023-07-05

揭秘Golang热更新机制:实现代码的热插拔方法详解

Golang热更新原理解密:如何实现代码热插拔,需要具体代码示例随着软件开发的快速发展,热更新已经成为了现代软件开发中的一个重要特性。热更新能够帮助开发人员在不停机的情况下,动态地添加、修改或删除代码,从而实现功能的更新和修复。在Gola
揭秘Golang热更新机制:实现代码的热插拔方法详解
2024-01-20

IndexedDB浏览器内建数据库并行更新问题详解

目录正文打开数据库并行更新问题正文IndexedDB 是一个浏览器内建的数据库,它比 localStorage 强大得多。通过支持多种类型的键,来存储几乎可以是任何类型的值。支撑事务的可靠性。支持键值范围查询、索引。和 localStor
2022-12-29

设置界面开发PreferenceLibrary数据重建机制详解

这篇文章主要为大家介绍了设置界面开发利器PreferenceLibrary数据重建机制详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-11-13

编程热搜

目录