React 中 setState 的异步操作案例详解

目录
  • 前言
  • React 中的 setState 为什么需要异步操作?
  • 什么时候setState会进行同步操作?

前言

在使用state的时候, 如果我们企图直接修改state中的某一个值之后直接打印(使用)他,就会发现,他其实并没有改变。

就像下面的例子,企图通过点击事件之后就使用修改之后的state的值,但是会发state中的并没有被立即修改,还是原先的值,我们都知道那是因为 setState就相当于是一个异步操作,不能立即被修改。

import React, { Component } from 'react';
export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '今天是七夕节'
    };
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    this.setState({
      name: '跟你这只单身狗有什么关系'
    })
    console.log(this.state.name)
  }

  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
        <button onClick={this.handleClick}>点击查看</button>
      </div>
    )
  }
}

还是只能获取到之前的值。但是我们就是想要立即获取,咋整呢

第一种:

这个回调函数会在修改了state之后才会执行,这就可以使用修改之后的state的值。

import React, { Component } from 'react';

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '今天是七夕节'
    };
    this.handleClick = this.handleClick.bind(this)
  }

  handleClick() {
    this.setState({
      name: '跟你这只单身狗有什么关系'
    }, () => {
      console.log(this.state.name)
    })
  }

  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
        <button onClick={this.handleClick}>点击查看</button>
      </div>
    )
  }
}

第二种:

操作异步函数,用 async / await

import React, { Component } from 'react';

export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '今天是七夕节'
    };
    this.handleClick = this.handleClick.bind(this)
  }
  async handleClick() {
    await this.setState({
      name: '跟你这只单身狗有什么关系'
    })
    console.log(this.state.name)
  }
  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
        <button onClick={this.handleClick}>点击查看</button>
      </div>
    )
  }
}

第三种:

setstate 可以接收一个回调函数,而不是一个对象,这个回调函数有两个参数,一个是接收前一个状态值作为第一个参数,并将更新后的值作为第二个参数。

import React, { Component } from 'react';
export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: '今天是七夕节'
    };
    this.handleClick = this.handleClick.bind(this)
  }
  handleClick() {
    this.setState(() => {
      return {
        name: `跟你这只单身狗有什么关系`
      }
    }, () => {
      console.log(this.state.name)
    })
  }
  render() {
    return (
      <div>
        <h1>{this.state.name}</h1>
        <button onClick={this.handleClick}>点击查看</button>
      </div>
    )
  }
}

还可以拿到之前的值,进行修改

handleClick() {
  this.setState((prevState) => {
    return {
      name: `${prevState.name},但是跟你这只单身狗有什么关系`
    }
  }, () => {
    console.log(this.state.name)
  })
}

react中 state的值在修改了之后并不会立即被修改,setState通过一个队列机制实现state的更新。当执行setState时,会把需要更新的state合并后放入状态队列,而不会立刻更新this.state,利用这个队列机制可以高效的批量的更新state。

setState之后不会立马触发更新,它会根据当前isBatchingUpdate 判断是否处于批量更新中,如果当前isBatchingUpdate为true,说明处于批量更新中,它会将要更新的值放入到一个队列中,随后将要更新的组件放入dirtyComponent中,当本次批量更新结束后,会将isBatchingUpdate中设置为false,开启本次的批量更新,情况队列,会用object.assign()将多次更新进行一个合并。 react会开启一个事务机制,进行dom diff算法等来进行跟新。

React 中的 setState 为什么需要异步操作?

  • 保持内部一致性:props 的更新是异步的,因为re-render父组件的时候,传入子组件的props才变化;为了保持数据一致,state也不直接更新,都是在flush的时候更新
  • 将state的更新延缓到最后批量合并再去渲染对于应用的性能优化是有极大好处的,如果每次的状态改变都去重新渲染真实 DONM,那么它将带来巨大的性能消耗
  • 立即更新回来视觉上的不适应,比如在页面打开时候,多个请求发布导致频繁更改Loading 状态,会导致 Loading 图标闪烁

什么时候setState会进行同步操作?

setState只在合成事件和钩子函数中是“异步”的,在原生事件和setTimeout 中都是同步的。

到此这篇关于React 中 setState 的异步操作案例详解的文章就介绍到这了,更多相关React setState异步内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • React中setState的使用与同步异步的使用

    在react中,修改状态如果直接使用this.state,不会引起组件的重新渲染,需要通过 this.setState来对组件的属性进行修改. 1.this.setState的两种定义方式 定义初始状态 state = { count: 0 }, 如果此时有一个按钮,点击按钮让计数加1,我们可以有两种写法 (1)传递对象 this.setState({ count: this.state.count + 1}) (2)传递函数 this.setState((state, props) => ({

  • 关于React中setState同步或异步问题的理解

    目录 1. setState同步?异步? 2. 表现为异步 1. React 合成事件 2. 生命周期函数 3. 表现为同步 1. 原生事件 2. setTimeout 4. setState的第二个参数 1. setState同步?异步? 在 React 的类式组件中,我们可以使用setState方法更新state状态.但有些时候使用setState之后,得不到最新的数据. 其实 React 中setState本身执行的过程和代码是同步的,只是因为 React 框架本身的性能优化机制而导致的.

  • React中setState同步异步场景的使用

    目录 setState同步异步场景 描述 原理 保证内部数据统一 启用并发更新 参考 setState同步异步场景 React通过this.state来访问state,通过this.setState()方法来更新state,当this.setState()方法被调用的时候,React会重新调用render方法来重新渲染UI.相比较于在使用Hooks完成组件下所需要的心智负担,setState就是在使用class完成组件下所需要的心智负担,当然所谓的心智负担也许叫做所必须的基础知识更加合适一些.

  • React 中的 setState 是同步还是异步

    setState 是同步还是异步?肯定是异步的呀. 确定么?那看一下这段代码会打印什么: import { Component } from 'react'; class Dong extends Component { constructor() { super(); this.state = { count: 0 } } componentDidMount() { setTimeout(() => { this.setState({ count: 1 }); console.log(this

  • 代码解析React中setState同步和异步问题

    React起源于Facebook的内部项目.React的出现是革命性的创新,React的是一个颠覆式的前端框架.在React官方这样介绍的它:一个声明式.高效.灵活的.创建用户界面的JavaScript库,即使React的主要作用是构建UI,但是项目的逐渐成长已经使得react成为前后端通吃的WebApp解决方案. angular中用的是watcher对象,vue是观察者模式,react就是state了,他们各有各的特点,没有好坏之分,只有需求不同而选择不同. React的官方网址:https:

  • React 中 setState 的异步操作案例详解

    目录 前言 React 中的 setState 为什么需要异步操作? 什么时候setState会进行同步操作? 前言 在使用state的时候, 如果我们企图直接修改state中的某一个值之后直接打印(使用)他,就会发现,他其实并没有改变. 就像下面的例子,企图通过点击事件之后就使用修改之后的state的值,但是会发state中的并没有被立即修改,还是原先的值,我们都知道那是因为 setState就相当于是一个异步操作,不能立即被修改. import React, { Component } fr

  • react.js框架Redux基础案例详解

    react.js框架Redux https://github.com/reactjs/redux 安装: npm install redux react-redux #基于react,我们在前面已经安装过了 Redux参考文档: http://redux.js.org/ Redux核心概念:Store 我们可以简单的理解为就是用来存储 各个组件的State或你自己定义的独立的state,对state进行统一读取.更新.监听等操作. http://redux.js.org/docs/basics/

  • react中的ajax封装实例详解

    react中的ajax封装实例详解 代码块 **opts: {'可选参数'} **method: 请求方式:GET/POST,默认值:'GET'; **url: 发送请求的地址, 默认值: 当前页地址; **data: string,json; **async: 是否异步:true/false,默认值:true; **cache: 是否缓存:true/false,默认值:true; **contentType: HTTP头信息,默认值:'application/x-www-form-urlenc

  • Web应用中设置Context Path案例详解

    URL:http://hostname.com/contextPath/servletPath/pathInfo Jetty 如果没有contextPath,则默认使用root上下文,root上下文的路径为"/". warName.war 在没有XML IoC文件的情况下: 如果WAR文件名是myapp.war,那么上下文路径是:/myapp: 如果WAR文件名是ROOT.war,那么上下文路径是:/: 如果WAR文件名是ROOT-foobar.war,那么上下文路径是/,虚拟host

  • JavaScript 中this指向问题案例详解

    总结 全局环境 ➡️ window 普通函数 ➡️ window 或 undefined 构造函数 ➡️ 构造出来的实例 箭头函数 ➡️ 定义时外层作用域中的 this 对象的方法 ➡️ 该对象 call().apply().bind() ➡️ 第一个参数 全局环境 无论是否在严格模式下,this 均指向 window 对象. console.log(this === window) // true // 严格模式 'use strict' console.log(this === window

  • Java list与set中contains()方法效率案例详解

    list.contains(o) :遍历集合所有元素,用每个元素和传入的元素进行 equals 比较,如果集合元素有 n 个,则会比较 n 次,所以时间复杂度为 O(n) .方法源码如下: // ArrayList 中的方法 public boolean contains(Object o) { return indexOf(o) >= 0; } public int indexOf(Object o) { if (o == null) { for (int i = 0; i < size;

  • SpringBoot在RequestBody中使用枚举参数案例详解

    前文说到 优雅的使用枚举参数 和 实现原理,本文继续说一下如何在 RequestBody 中优雅使用枚举. 本文先上实战,说一下如何实现.在 优雅的使用枚举参数 代码的基础上,我们继续实现. 确认需求 需求与前文类似,只不过这里需要是在 RequestBody 中使用.与前文不同的是,这种请求是通过 Http Body 的方式传输到后端,通常是 json 或 xml 格式,Spring 默认借助 Jackson 反序列化为对象. 同样的,我们需要在枚举中定义 int 类型的 id.String

  • C++中双冒号::用法案例详解

    C++中的双冒号 :: 第一种,类作用域,用来标明类的变量.函数 Human::setName(char* name); 第二种,命名空间作用域,用来注明所使用的类.函数属于哪一个命名空间的 std::cout << "Hello World" << std::endl; 第三种,全局作用域,用来区分局部.全局的.最容易被忽视的一种,很多时候写了一个全局函数或者想要调用一个全局函数,却发现IDE或者Editor找不到该函数,原因是因为局部函数与想要调用的全局函数

  • React中useLayoutEffect钩子使用场景详解

    目录 简介 useEffect钩子的概述 钩子流程 useLayoutEffect钩子的概述 钩子流程 什么时候使用useLayoutEffect钩子? 总结 简介 不久前,React对其功能组件进行了一次重大更新(在2019年3月的16.8版本中),终于为这些组件提供了一种变得有状态的方法. 钩子的加入不仅意味着功能组件将能够提供自己的状态,而且还能通过引入useEffect钩子来管理自己的生命周期事件. 此外,这次更新还引入了一个全新的useLayoutEffect钩子,根据React文档,

  • React中使用Vditor自定义图片详解

    安装 npm install vditor -s 引用 导入依赖包 import Vditor from "vditor"; 导入样式 import "vditor/src/assets/scss/index.scss"; 使用示例 export default class Vditor extends Component { constructor(props) { super(props); this.state = { editValue: "&qu

随机推荐