热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

你真的了解setState()吗?

React中setState()详细解读对于setState()相信伙伴们都用过,它是React官方推荐用来更新组件state的API,但是对于setState()你真的了解吗?且

React 中 setState()详细解读

对于 setState() 相信伙伴们都用过,它是 React 官方推荐用来更新组件 state 的 API,但是对于 setState() 你真的了解吗?且待我慢慢详聊一番。


setState() 官方用法指南

语法1: setState(updater[, callback])



  • updater:函数类型,返回一个更新后的 state 中的状态对象,它会和 state 进行浅合并。


  • callback: 可选,回调函数。


语法2: setState(stateChange[, callback])



  • setState: 对象类型,会将传入的对象浅层合并到新的 state 中。


  • callback:可选,回调函数。


对于这两种形式,不同的是第一个参数选择问题,可以选择一个函数返回一个新的state对象,亦可以直接选择一个对象应用于状态更新,那么啥时候选择函数类型的参数,什么时候选择对象类型的呢?这里可以总结两句话:



  • 当前状态更新无需依赖之前的state状态时,选择对象类型参数


  • 当前更新状态依赖之前的状态时,选择函数类型参数


example:
















这个例子中,我们通过点击按钮测试1或测试2来改变组件 A 的 count 状态值,因为每次修改状态都是在原先基础上加 1, 所以在setState 中适合选择函数类型参数,即 update2 写法推荐。

点击 测试3 按钮会直接将count 值修改为 固定值 8,这无需依赖上一次count状态值,所以在setState 中适合选择对象类型参数,即 update3 写法推荐。


setState() 更新状态一定是异步的吗?

我们知道setState() 会触发组件render() 函数,重新渲染组件将更新后的内容显示在视图上,那么在 setState() 之后我们立马就能获取到最新的state值吗?

这里涉及到一个 setState() 是异步更新还是同步更新的问题?

结论:



  • 在React相关的回调函数中setState() 是异步更新


  • 不在React 相关的回调中setState() 是同步更新


React 相关的回调包括:组件的生命周期钩子,React 组件事件监听回调。

React不相关的回调包括常见的:setTimeout(), Promise()等。

我们还是可以拿之前的按钮点击实例来测试。

example:
















我们在 React 事件监听回调 update1 和 组件生命周期 componentWillMount() 钩子里面分别在setState()之后打印最新的 state 值,发现打印出来的还是修改之前的state,但是页面已经更新为最新状态,看图:

采用同样的方法我们可以观察在 update2 的setTimeout() 和 update3 的 Promise() 回调中,setState() 后打印的是最新的state值,而且这个打印会在setState() 触发组件重新render() 之后。经过测试,恰好验证了我们的结论是正确的,在React 相关的回调中setState()是异步更新状态,在不相关的回调中 setState() 是同步更新状态。


setState() 异步更新状态时,如何获取最新的状态值?

这个问题其实是针对当setState() 异步更新状态之后,怎么立马获取到最新的状态值,也就是上面例子我们说的在update1() 和componentWillMount()中怎么打印出最新的state值。

答案其实非常简单,也就是我们说到的setState()传参的第二个callback() 参数。setState() 的第二个回调会在更新状态之后,组件重新render() 之后调用,也就是这里面我们可以获取到最新的状态值。

代码:


...
update1 = () => {
this.setState({count: this.state.count+1}, () => {
console.log(this.state.count)
})
}
componentWillMount () {
this.setState(state => ({
count: state.count+1
}), () => {
console.log(this.state.count)
})
}

这样,我们同样可以在update1 和 componentWillMount() 中 打印出最新的state值。


遇到重复多次调用setState(),React如何处理?

这里我们讨论的前提当然是setState() 异步更新状态时候,因为同步更新,我们调用几次 setState(),就会触发几次 render钩子,当然也会实时分别打印出更新后的状态值。

结论:

这里分两种情况讨论:



  • 当setState() 传对象类型参数,React会合并重复多次的调用setState(),触发一次render。


  • 当setState() 传函数类型参数,React会依次多次的调用setState(),触发一次render。


可以看到,我们多次重复调用setState(),不管是传参是何种类型。React都只会调用一次 render,重新渲染组件。

我们可以同样以按钮点击实例来测试我们结论。

example:
















当点击测试按钮2,因为setState() 是同步更新状态,可以发现组件进行了多次render调用,分别依次打印出更新后的状态值,这个很简单。

我们点击测试按钮1,分别对传给setState()参数不同进行了测试,发现当传参是对象类型时候,React会合并重复setState()调用,也就是只更新一次state状态,传函数类型参数时候,则分别进行了计算更新。

无论以哪种方式传参重复调用 setState() ,React 都只会进行一次render 调用,这也是性能优化的一部分,防止多次重复渲染带来的性能问题。

其实官网推荐我们使用setState()时候,第一个参数传函数类型参数,因为函数参数中接收的 state 和 props 都保证为最新。



推荐阅读
  • wpf+mvvm代码组织结构及实现方式
    本文介绍了wpf+mvvm代码组织结构的由来和实现方式。作者回顾了自己大学时期接触wpf开发和mvvm模式的经历,认为mvvm模式使得开发更加专注于业务且高效。与此同时,作者指出mvvm模式相较于mvc模式的优势。文章还提到了当没有mvvm时处理数据和UI交互的例子,以及前后端分离和组件化的概念。作者希望能够只关注原始数据结构,将数据交给UI自行改变,从而解放劳动力,避免加班。 ... [详细]
  • 本文介绍了C#中生成随机数的三种方法,并分析了其中存在的问题。首先介绍了使用Random类生成随机数的默认方法,但在高并发情况下可能会出现重复的情况。接着通过循环生成了一系列随机数,进一步突显了这个问题。文章指出,随机数生成在任何编程语言中都是必备的功能,但Random类生成的随机数并不可靠。最后,提出了需要寻找其他可靠的随机数生成方法的建议。 ... [详细]
  • Google Play推出全新的应用内评价API,帮助开发者获取更多优质用户反馈。用户每天在Google Play上发表数百万条评论,这有助于开发者了解用户喜好和改进需求。开发者可以选择在适当的时间请求用户撰写评论,以获得全面而有用的反馈。全新应用内评价功能让用户无需返回应用详情页面即可发表评论,提升用户体验。 ... [详细]
  • 深入理解Kafka服务端请求队列中请求的处理
    本文深入分析了Kafka服务端请求队列中请求的处理过程,详细介绍了请求的封装和放入请求队列的过程,以及处理请求的线程池的创建和容量设置。通过场景分析、图示说明和源码分析,帮助读者更好地理解Kafka服务端的工作原理。 ... [详细]
  • 服务器上的操作系统有哪些,如何选择适合的操作系统?
    本文介绍了服务器上常见的操作系统,包括系统盘镜像、数据盘镜像和整机镜像的数量。同时,还介绍了共享镜像的限制和使用方法。此外,还提供了关于华为云服务的帮助中心,其中包括产品简介、价格说明、购买指南、用户指南、API参考、最佳实践、常见问题和视频帮助等技术文档。对于裸金属服务器的远程登录,本文介绍了使用密钥对登录的方法,并提供了部分操作系统配置示例。最后,还提到了SUSE云耀云服务器的特点和快速搭建方法。 ... [详细]
  • 本文介绍了一个React Native新手在尝试将数据发布到服务器时遇到的问题,以及他的React Native代码和服务器端代码。他使用fetch方法将数据发送到服务器,但无法在服务器端读取/获取发布的数据。 ... [详细]
  • 一、什么是闭包?有什么作用什么是闭包闭包是定义在一个函数内部的函数,它可以访问父级函数的内部变量。当一个闭包被创建时,会关联一个作用域—— ... [详细]
  • 从零基础到精通的前台学习路线
    随着互联网的发展,前台开发工程师成为市场上非常抢手的人才。本文介绍了从零基础到精通前台开发的学习路线,包括学习HTML、CSS、JavaScript等基础知识和常用工具的使用。通过循序渐进的学习,可以掌握前台开发的基本技能,并有能力找到一份月薪8000以上的工作。 ... [详细]
  • 恶意软件分析的最佳编程语言及其应用
    本文介绍了学习恶意软件分析和逆向工程领域时最适合的编程语言,并重点讨论了Python的优点。Python是一种解释型、多用途的语言,具有可读性高、可快速开发、易于学习的特点。作者分享了在本地恶意软件分析中使用Python的经验,包括快速复制恶意软件组件以更好地理解其工作。此外,作者还提到了Python的跨平台优势,使得在不同操作系统上运行代码变得更加方便。 ... [详细]
  • 本文总结了在编写JS代码时,不同浏览器间的兼容性差异,并提供了相应的解决方法。其中包括阻止默认事件的代码示例和猎取兄弟节点的函数。这些方法可以帮助开发者在不同浏览器上实现一致的功能。 ... [详细]
  • 本文是一篇翻译文章,介绍了async/await的用法和特点。async关键字被放置在函数前面,意味着该函数总是返回一个promise。文章还提到了可以显式返回一个promise的方法。该特性使得async/await更易于理解和使用。本文还提到了一些可能的错误,并希望读者能够指正。 ... [详细]
  • 前段时间做一个项目,需求是对每个视频添加预览图,这个问题最终选择方案是:用canvas.toDataYRL();来做转换获取视频的一个截图,添加到页面中,达到自动添加预览图的目的。 ... [详细]
  • 工作经验谈之-让百度地图API调用数据库内容 及详解
    这段时间,所在项目中要用到的一个模块,就是让数据库中的内容在百度地图上展现出来,如经纬度。主要实现以下几点功能:1.读取数据库中的经纬度值在百度上标注出来。2.点击标注弹出对应信息。3 ... [详细]
  • 1、打开etcsysconfiggrub,   #vimetcsysconfiggrub   内容如下: ... [详细]
  • javascript二叉树基本功能实现
    都是常用的功能。删除是最复杂的。。test ... [详细]
author-avatar
魏承辉符合_821
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有