React中setState/useState的使用方法詳細(xì)介紹
一、React如何使用setState/useState的最新的值
一般是可以正常的把最新的值,傳遞給所需要的函數(shù)中的,但是有些情況,需要使用最新數(shù)據(jù)的函數(shù),不可改動,甚至所需要使用的地方并不是一個函數(shù),那我們?nèi)绾潍@取setState/useState的最新的值呢?
A.使用setState的最新的值
1、setState方法可以接收兩個參數(shù),第一個參數(shù)為一個對象,第二個參數(shù)為一個函數(shù),即更新成功后執(zhí)行的回調(diào)函數(shù)。我們可以在回調(diào)函數(shù)中獲取更新后的值。
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); //* 刪除啟明相關(guān)字段的數(shù)據(jù)
}
const initData = useCallback(async () => {
await commonQuery(basicInfoHeader, { contractId });
const qimingFlagNow = basicInfoHeader.current?.get('qimingFlag');
setQimingFlag(qimingFlagNow); //* 用于出發(fā)重新渲染
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執(zhí)行的同步異步問題
只要代碼進(jìn)入了 react調(diào)度流程,那就是異步的。
只要代碼沒有進(jìn)入 react調(diào)度流程,那就是同步的。
setTimeout、setInterval、async中await的后續(xù)部分,Promise.then(),以及直接在 DOM 上綁定原生事件等。這些都不會走 React調(diào)度流程,在這種情況下調(diào)用 setState ,那這次 setState 就是同步的。 否則就是異步的。
連續(xù)執(zhí)行兩個 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}- 【不受react調(diào)度】</button>
<button onClick={inControl} >{a}- 【react調(diào)度】</button>
</>
)
}
//! 當(dāng)點擊【不受react調(diào)度】按鈕時,render 了兩次
//! 當(dāng)點擊【react調(diào)度】按鈕時,只重新 render 了一次
連續(xù)執(zhí)行兩次同一個 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調(diào)度】</button>
<button onClick={inControl} >{a} 【react調(diào)度】</button>
</>
)
}
//! 當(dāng)點擊【不受react調(diào)度】按鈕時,兩次 setA 各自 render 一次,分別打印 2,3
//! 當(dāng)點擊【react調(diào)度】按鈕時,兩次 setA 都執(zhí)行,但合并 render 了一次,打印 3
連續(xù)執(zhí)行兩個 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調(diào)度】</button>
<button onClick={this.inControl} >【react調(diào)度】</button>
</>
)
}
}
//! 當(dāng)點擊【不受react調(diào)度】按鈕時,render 了兩次
//! 當(dāng)點擊【react調(diào)度】按鈕時,只重新 render 了一次
連續(xù)執(zhí)行兩次同一個 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調(diào)度】</button>
<button onClick={this.inControl} >【react調(diào)度】</button>
</>
)
}
}
//! 當(dāng)點擊【不受react調(diào)度】按鈕時,兩次 setState 各自 render 一次,分別打印 2,3
//! 當(dāng)點擊【react調(diào)度】按鈕時,兩次 setState 合并,只執(zhí)行了最后一次,打印 2
總結(jié)
在正常的react調(diào)度流程中時:
- setState和useState都是異步執(zhí)行的
- 多次執(zhí)行setState和useState,會進(jìn)行一次batchUpdate,只會重新渲染render一次
- 不同的是,多次執(zhí)行,setState會進(jìn)行state的合并,而useState每次運行都會重新計算
不再react調(diào)度流程中時
- setState和useState是同步執(zhí)行的(立即更新state,觸發(fā)render,然后繼續(xù)執(zhí)行)
- 多次執(zhí)行setState和useState,每一次的執(zhí)行setState和useState,都會調(diào)用一次render
到此這篇關(guān)于React中setState/useState的使用方法詳細(xì)介紹的文章就介紹到這了,更多相關(guān)React setState/useState內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
React Native中實現(xiàn)動態(tài)導(dǎo)入的示例代碼
隨著業(yè)務(wù)的發(fā)展,每一個 React Native 應(yīng)用的代碼數(shù)量都在不斷增加。作為一個前端想到的方案自然就是動態(tài)導(dǎo)入(Dynamic import)了,本文介紹了React Native中實現(xiàn)動態(tài)導(dǎo)入的示例代碼,需要的可以參考一下2022-06-06
ReactQuery系列React?Query?實踐示例詳解
這篇文章主要為大家介紹了ReactQuery系列React?Query?實踐示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11
react性能優(yōu)化達(dá)到最大化的方法 immutable.js使用的必要性
這篇文章主要為大家詳細(xì)介紹了react性能優(yōu)化達(dá)到最大化的方法,一步一步優(yōu)化react性能的過程,告訴大家使用immutable.js的必要性,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03
react搭建環(huán)境時執(zhí)行npm start報錯start: 'react-scripts&
這篇文章主要介紹了react搭建環(huán)境時執(zhí)行npm start報錯start: 'react-scripts start'的解決方案,具有很好的參考價值,希望杜對大家有所幫助,2023-10-10

