React中setState/useState的使用方法详细介绍

 更新时间:2023年04月06日 10:00:32   作者:英俊潇洒美少年  
这篇文章主要介绍了React中setState/useState的使用方法,useState 和 setState 在React开发过程中 使用很频繁,但很多人都停留在简单的使用阶段,并没有正在了解它们的执行机制

一、React如何使用setState/useState的最新的值

一般是可以正常的把最新的值,传递给所需要的函数中的,但是有些情况,需要使用最新数据的函数,不可改动,甚至所需要使用的地方并不是一个函数,那我们如何获取setState/useState的最新的值呢?

A.使用setState的最新的值

1、setState方法可以接收两个参数,第一个参数为一个对象,第二个参数为一个函数,即更新成功后执行的回调函数。我们可以在回调函数中获取更新后的值。

import React, { Component } from 'react'
export default class DemoClassComp extends Component {
  constructor(props) {
    super(props)
    this.state = {
      number: 1,
    }
  }
  inControl = ()=>{
    this.setState({number: 1}, () => {
      console.log('%c 📯 DemoClassComp -> inControl -> this.state.number ', 'font-size:16px;background-color:#f31440;color:white;', this.state.number)
    })
  }
  render() {
    return (
      <div>
        <button onClick={this.inControl} >点我</button>
      </div>
    )
  }
}

2、使用setTimeout

B.使用useState的最新的值

1、使用另一个Hook,useRef;

function DemoFuncComp() {
  const [qimingFlag, setQimingFlag] = useState(false);
  const qimingFlagRef = useRef(false);
  const handleLine = () => {
    deleteQimingFieldsData(data, qimingFlagRef?.current); //* 删除启明相关字段的数据
  }
  const initData = useCallback(async () => {
    await commonQuery(basicInfoHeader, { contractId });
    const qimingFlagNow = basicInfoHeader.current?.get('qimingFlag');
    setQimingFlag(qimingFlagNow); //* 用于出发重新渲染
    qimingFlagRef.current = qimingFlagNow;
    handleLine(); //* 要求 先setQimingFlag
  }, [contractId])
  /**生命周期 */
  useEffect(() => {
    initData();
  }, [contractId]);
  return (
    <>
      <Form dataSet={basicInfoHeader} disabled={true} columns={4}>
        <Lov name="receiverObj" />
    </Form>
    </>
  )
}

2、使用setTimeout

二、React中setState/useState执行的同步异步问题

只要代码进入了 react调度流程,那就是异步的。

只要代码没有进入 react调度流程,那就是同步的。

setTimeout、setInterval、async中await的后续部分,Promise.then(),以及直接在 DOM 上绑定原生事件等。这些都不会走 React调度流程,在这种情况下调用 setState ,那这次 setState 就是同步的。 否则就是异步的。

连续执行两个 useState

function DemoFuncComp() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);
  console.log('render')
  function outControl() {
    Promise.resolve().then(() => {
      setA((a) => a + 1);
      setB((b) => b + 1);
    })
  }
  function inControl() {
    setA((a) => a + 1);
    setB((b) => b + 1);
  }
  return (
    <>
      <button onClick={outControl} >{a}-{b} 【不受react调度】</button>
      <button onClick={inControl} >{a}-{b} 【react调度】</button>
    </>
  )
}
//! 当点击【不受react调度】按钮时,render 了两次
//! 当点击【react调度】按钮时,只重新 render 了一次

连续执行两次同一个 useState

function DemoFuncComp() {
  const [a, setA] = useState(1)
  console.log('a', a)
  function outControl() {
    Promise.resolve().then(() => {
      setA((a) => a + 1)
      setA((a) => a + 1)
    })
  }
  function inControl() {
    setA((a) => a + 1)
    setA((a) => a + 1)
  }
  return (
    <>
      <button onClick={outControl} >{a} 【不受react调度】</button>
      <button onClick={inControl} >{a} 【react调度】</button>
    </>
  )
}
//! 当点击【不受react调度】按钮时,两次 setA 各自 render 一次,分别打印 2,3
//! 当点击【react调度】按钮时,两次 setA 都执行,但合并 render 了一次,打印 3

连续执行两个 setState

class DemoClassComp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      a: 1,
      b: 'b',
    }
  }
  outControl = () => {
    Promise.resolve().then(() => {
      this.setState({...this.state, a: 'aa'})
      this.setState({...this.state, b: 'bb'})
    })
  }
  inControl = () => {
    this.setState({...this.state, a: 'aa'})
    this.setState({...this.state, b: 'bb'})
  }
  render() {
    console.log('render')
    return (
      <>
        <button onClick={this.outControl} >【不受react调度】</button>
        <button onClick={this.inControl} >【react调度】</button>
      </>
    )
  }
}
//! 当点击【不受react调度】按钮时,render 了两次
//! 当点击【react调度】按钮时,只重新 render 了一次

连续执行两次同一个 setState

class DemoClassComp extends React.Component {
  constructor(props) {
    super(props)
    this.state = {
      a: 1,
    }
  }
  outControl = () => {
    Promise.resolve().then(() => {
      this.setState({a: this.state.a + 1})
      this.setState({a: this.state.a + 1})
    })
  }
  inControl = () => {
    this.setState({a: this.state.a + 1})
    this.setState({a: this.state.a + 1})
  }
  render() {
    console.log('a', this.state.a)
    return (
      <>
        <button onClick={this.outControl} >【不受react调度】</button>
        <button onClick={this.inControl} >【react调度】</button>
      </>
    )
  }
}
//! 当点击【不受react调度】按钮时,两次 setState 各自 render 一次,分别打印 2,3
//! 当点击【react调度】按钮时,两次 setState 合并,只执行了最后一次,打印 2

总结

在正常的react调度流程中时:

  • setState和useState都是异步执行的
  • 多次执行setState和useState,会进行一次batchUpdate,只会重新渲染render一次
  • 不同的是,多次执行,setState会进行state的合并,而useState每次运行都会重新计算

不再react调度流程中时

  • setState和useState是同步执行的(立即更新state,触发render,然后继续执行)
  • 多次执行setState和useState,每一次的执行setState和useState,都会调用一次render

到此这篇关于React中setState/useState的使用方法详细介绍的文章就介绍到这了,更多相关React setState/useState内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • react时间分片实现流程详解

    react时间分片实现流程详解

    实现react时间分片,主要内容包括什么是时间分片、为什么需要时间分片、实现分片开启 - 固定、实现分片中断、重启 - 连续、分片重启、实现延迟执行 - 有间隔、时间分片异步执行方案的演进、时间分片简单实现、总结、基本概念、基础应用、原理机制和需要注意的事项等
    2022-11-11
  • React 全自动数据表格组件——BodeGrid的实现思路

    React 全自动数据表格组件——BodeGrid的实现思路

    表格是在后台管理系统中用的最频繁的组件之一,相关的功能有数据的新增和编辑、查询、排序、分页、自定义显示以及一些操作按钮。这篇文章主要介绍了React 全自动数据表格组件——BodeGrid ,需要的朋友可以参考下
    2019-06-06
  • React组件学习之Hooks使用

    React组件学习之Hooks使用

    这篇文章主要介绍了React hooks组件通信,在开发中组件通信是React中的一个重要的知识点,本文通过实例代码给大家讲解react hooks中常用的父子、跨组件通信的方法,需要的朋友可以参考下
    2022-08-08
  • 浅谈React Event实现原理

    浅谈React Event实现原理

    这篇文章主要介绍了浅谈React Event实现原理,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-09-09
  • react组件多次渲染问题的解决

    react组件多次渲染问题的解决

    本文主要介绍了react组件多次渲染问题的解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-07-07
  • 想用好React的你必须要知道的一些事情

    想用好React的你必须要知道的一些事情

    现在最热门的前端框架,毫无疑问是 React 。下面这篇文章主要给大家分享了关于想用好React的你必须要知道的一些事情,文中介绍的非常详细,对大家具有一定参考学习价值,需要的朋友们下面来一起看看吧。
    2017-07-07
  • react国际化化插件react-i18n-auto使用详解

    react国际化化插件react-i18n-auto使用详解

    这篇文章主要介绍了react国际化化插件react-i18n-auto使用详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • React受控组件与非受控组件深入讲解

    React受控组件与非受控组件深入讲解

    具体来说这是一种react非受控组件,其状态是在input的react内部控制,不受调用者控制。可以使用受控组件来实现。下面就说说这个React中的受控组件与非受控组件的相关知识,感兴趣的朋友一起看看吧
    2022-12-12
  • Electron+React进行通信的方法

    Electron+React进行通信的方法

    electron其实是一个桌面应用程序,不是一个标准的前端web程序,所有没有什么请求的发生,控制台network看不到请求,而是只能通过console.log去打印查看,而且通信协议使用的不是http而是gRPC协议,这篇文章主要介绍了Electron+React如何进行通信,需要的朋友可以参考下
    2022-06-06
  • React Hook 四种组件优化总结

    React Hook 四种组件优化总结

    这篇文章主要介绍了React Hook四种组件优化总结,文章围绕主题展开详细的内容介绍,具有一定的参考价孩子,需要的朋友可以参考一下
    2022-07-07

最新评论