React中setState/useState的使用方法详细介绍
作者:英俊潇洒美少年
这篇文章主要介绍了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内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!