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 Native中实现动态导入的示例代码

    React Native中实现动态导入的示例代码

    随着业务的发展,每一个 React Native 应用的代码数量都在不断增加。作为一个前端想到的方案自然就是动态导入(Dynamic import)了,本文介绍了React Native中实现动态导入的示例代码,需要的可以参考一下
    2022-06-06
  • ReactQuery系列React Query 实践示例详解

    ReactQuery系列React Query 实践示例详解

    这篇文章主要为大家介绍了ReactQuery系列React Query 实践示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-11-11
  • react性能优化达到最大化的方法 immutable.js使用的必要性

    react性能优化达到最大化的方法 immutable.js使用的必要性

    这篇文章主要为大家详细介绍了react性能优化达到最大化的方法,一步一步优化react性能的过程,告诉大家使用immutable.js的必要性,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-03-03
  • react中用less的问题

    react中用less的问题

    本文主要介绍了react中用less的问题,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-04-04
  • React Hooks 实现的中文输入组件

    React Hooks 实现的中文输入组件

    这篇文章主要为大家介绍了React Hooks实现的中文输入组件示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • react中的axios模块你了解吗

    react中的axios模块你了解吗

    这篇文章主要为大家详细介绍了react中的axios模块,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-03-03
  • React中setState同步异步场景的使用

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

    本文主要介绍了React中setState同步异步场景的使用,文中根据实例编码详细介绍的十分详尽,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-03-03
  • react中使用useEffect及踩坑记录

    react中使用useEffect及踩坑记录

    这篇文章主要介绍了react中使用useEffect及踩坑记录,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08
  • react搭建环境时执行npm start报错start: 'react-scripts start'的解决

    react搭建环境时执行npm start报错start: 'react-scripts&

    这篇文章主要介绍了react搭建环境时执行npm start报错start: 'react-scripts start'的解决方案,具有很好的参考价值,希望杜对大家有所帮助,
    2023-10-10
  • 使用React.forwardRef传递泛型参数

    使用React.forwardRef传递泛型参数

    这篇文章主要介绍了使用React.forwardRef传递泛型参数方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-05-05

最新评论