百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 热门文章 > 正文

你真的会用setState吗?

bigegpt 2025-05-23 15:29 5 浏览

setState函数是什么?

1. 将需要处理的变化塞入组建的state对象中

2. 告诉该组件及其子组件需要用更新的状态来重新渲染

3. 响应事件处理和服务端响应更新用户界面的主要方式

setState经典例子

constructor(props) {
    super(props);
    this.state = {
        count: 0
    };
    this.increase = this.increase.bind(this);
}

increase() {
    this.setState({ count: this.state.count + 1 });
    // 第一次输出
    console.log('第一次输出:', this.state.count);
    
    this.setState({ count: this.state.count + 1 });
    // 第二次输出
    console.log('第二次输出:', this.state.count);
    
    setTimeout(() => {
        this.setState({ count: this.state.count + 1 });
        // 第三次输出
        console.log('第三次输出:', this.state.count);
        
        this.setState({ count: this.state.count + 1 });
        // 第四次输出
        console.log('第四次输出:', this.state.count);
    }, 1000)
}

不知道你们心里是否有上面代码的答案了呢?不错,正确输出是:0 0 2 3。那可能刚开始学React的童鞋就会问了?为什么前面都是0,后面的正常加了了?那这个setState究竟是同步的还是异步的了?那么,接下来就为你解答心中的疑惑=。=

合并更新

前两次的setState,不会立即改变React组件中的state的值,这两次输出的都是0;合并更新,将多次的setState合并成一次,不引发重复渲染

setTimeout 同步更新,引发两次渲染。

setState是异步的吗?

其实,这只是React的障眼法。

setState是同步执行的!但是state并不一定会同步更新(异步更新和同步更新都存在)

那setState究竟干了什么了?

setState()中有个特别重要的布尔属性isBatchingUpdates(默认为false),它决定了state是同步更新还是异步更新

setState只在合成事件何钩子函数中是“异步更新”的。


异步更新的背后,是同步代码处理(“合成事件何钩子函数”的调用在“更新”前)。


异步是为了实现批量更新的手段,也是React新能优化的一种方式。

为什么直接修改this.state无效

要知道setState本质是通过一个队列机制实现state更新的。执行setState时,会将需要更新的state合并后放入状态队列,而不会立刻更新state,队列机制可以批量更新state。如果不通过setState而直接修改this.state,那么这个state不会放入状态队列中,下次调用setState时,状态队列新进行合并时,会忽略之前直接被修改的state,这样我们就无法合并了,而且实际也没有把你想要的state更新上去。

React.setState中的同步更新

当然了,我们也是有办法同步获取state更新后的值:

  1. setTimeout等异步操作中调用setState函数
  2. DOM原生事件
  3. 利用setState回调函数
  4. 函数式setState用法

前两个都是比较好理解,因为没有前置的 batchdUpdate 调用,所以 isBatchingUpdates false。不会开启批量更新模式。

后面两个方法,是React本身提供的。要注意的是,setState回调函数要在render函数被重新执行后才执行。

// 回调函数
this.setState({ count: 1 }, () => {
    console.log(this.state.count)
})

// 函数式
this.setState(prevState => {
    return {
        count: prevState.count + 1
    }
})

对比VUE批量更新

Vue在监听到数据变化后,会开启一个队列,并缓冲在同一事件循环中发生的所有数据变更(如果同一个watcher被多次触发,只会被推入到队列中一次)。然后,在下一次事件循环Tick/微任务中,Vue刷新队列执行实际工作。

vue批量更新体现为

  1. Mutation Observer(变动观察器)是侦听DOM变动的接口。当DOM对象树发生任何变动时,Mutation Observer会得到通知。
  2. 概念上,它很接近事件。可以理解为,当DOM发生变动会触发Mutation Observer事件。但是,它与事件有一个本质区别:事件是同步触发,DOM发生变化会立刻触发响应的事件
  3. Mutation Observer是异步触发,DOM发生变动,并不会立刻触发,而是要等到当前所有DOM操作都结束后才会触发。

针对以上的知识点,我们来看看下面这段代码,看我们是否理解setState:

class Demo extends React.Component {
  state = {
    count: 0,
  };
  componentDidMount() {
    this.setState({
      count: this.state.count + 1,
    });
    console.log("console: " + this.state.count);

    this.setState({ count: this.state.count + 1 }, () => {
      console.log("console from callback: " + this.state.count);
    });

    this.setState(
      (prevState) => {
        console.log("console from func: " + prevState.count);
        return {
          count: prevState.count + 1,
        };
      },
      () => {
        console.log("last console: " + this.state.count);
      }
    );
  }

  render() {
    console.log("render: " + this.state.count);
    return <h4>test</h4>;
  }
}

总结

  1. state更新需要通过setState,而不能直接操作state。
  2. 调用setState更新,state不会立刻生效。
  3. 多个顺序执行的setState不是同步一个个执行,会加入到一个队列中,然后最后一起执行,及批量更新。

相关推荐

Linux 系统启动完整流程

一、启动系统流程简介如上图,简述系统启动的大概流程:1:硬件引导UEFi或BIOS初始化,运行POST开机自检2:grub2引导阶段系统固件会从MBR中读取启动加载器,然后将控制权交给启动加载器GRU...

超专业解析!10分钟带你搞懂Linux中直接I/O原理

我们先看一张图:这张图大体上描述了Linux系统上,应用程序对磁盘上的文件进行读写时,从上到下经历了哪些事情。这篇文章就以这张图为基础,介绍Linux在I/O上做了哪些事情。文件系统什么是...

linux入门系列12--磁盘管理之分区、格式化与挂载

前面系列文章讲解了VI编辑器、常用命令、防火墙及网络服务管理,本篇将讲解磁盘管理相关知识。本文将会介绍大量的Linux命令,其中有一部分在“linux入门系列5--新手必会的linux命令”一文中已经...

Linux环境下如何设置多个交叉编译工具链?

常见的Linux操作系统都可以通过包管理器安装交叉编译工具链,比如Ubuntu环境下使用如下命令安装gcc交叉编译器:sudoapt-getinstallgcc-arm-linux-gnueab...

可算是有文章,把Linux零拷贝技术讲透彻了

阅读本文大概需要6.0分钟。作者:卡巴拉的树链接:https://dwz.cn/BaQWWtmh本文探讨Linux中主要的几种零拷贝技术以及零拷贝技术适用的场景。为了迅速建立起零拷贝的概念...

linux软链接的创建、删除和更新

大家都知道,有的时候,我们为了省下空间,都会使用链接的方式来进行引用操作。同样的,在系统级别也有。在Windows系列中,我们称其为快捷方式,在Linux中我们称其为链接(基本上都差不多了,其中可能...

Linux 中最容易被黑客动手脚的关键目录

在Linux系统中,黑客攻击后常会针对关键目录和文件进行修改以实现持久化、提权或隐藏恶意活动。本文介绍下黑客最常修改的目录及其手法。一、/etc目录关键文件有:/etc/passwd和/et...

linux之间传文件命令之Rsync傻瓜式教程

1.前言linux之间传文件命令用什么命令?本文介绍一种最常用,也是功能强大的文件同步和传输工具Rsync,本文提供详细傻瓜式教程。在本教程中,我们将通过实际使用案例和最常见的rsync选项的详细说...

Linux下删除目录符号链接的方法

技术背景在Linux系统中,符号链接(symlink)是一种特殊的文件,它指向另一个文件或目录。有时候,我们可能需要删除符号链接,但保留其指向的目标目录。然而,在删除符号链接时可能会遇到一些问题,例如...

阿里云国际站注册教程:aa云服务器怎么远程链接?

在全球化的今天,互联网带给我们无以计数的便利,而云服务器则是其中的重要基础设施之一。这篇文章将围绕阿里云国际站注册、aa云服务器如何远程链接,以及服务器安全防护如Ddos防火墙、网站应用防护waf防火...

Linux 5.16 网络子系统大范围升级 多个新适配器驱动加入

Linux在数据中心中占主导地位,因此每个内核升级周期的网络子系统变化仍然相当活跃。Linux5.16也不例外,周一最新与网络相关的更新加入了大量的驱动和新规范的支持。一个较新硬件的驱动是Realt...

搭建局域网文件共享服务(Samba),手机电脑都能看喜欢的影视剧

作为一名影视爱好者,为了方便地观看自己喜欢的影视作品,在家里搞一个专门用来存放电影的服务器是有必要的。蚁哥选则用一台Ubuntu系统的电脑做为服务器,共享影音文件,其他同一个局域网内的电脑或手机可以...

分享一个实用脚本—centos7系统巡检

概述这周闲得慌,就根据需求写了差不多20个脚本(部分是之前分享过的做了一些改进),今天主要分享一个给平时运维人员用的centos7系统巡检的脚本,或者排查问题检查系统情况也可以用..实用脚本#!/bi...

Linux 中创建符号链接的方法

技术背景在Linux系统里,符号链接(SymbolicLink),也被叫做软链接(SoftLink),是一种特殊的文件,它指向另一个文件或者目录。符号链接为文件和目录的管理带来了极大的便利,比...

一文掌握 Linux 符号链接

符号链接(SymbolicLink),通常被称为“软链接”,是Linux文件系统中一种强大而灵活的工具。它允许用户创建指向文件或目录的“快捷方式”,不仅简化了文件管理,还在系统配置、软件开发和日...