React中setState/useState的使用方法詳細(xì)介紹
一、React如何使用setState/useState的最新的值
一般是可以正常的把最新的值,傳遞給所需要的函數(shù)中的,但是有些情況,需要使用最新數(shù)據(jù)的函數(shù),不可改動(dòng),甚至所需要使用的地方并不是一個(gè)函數(shù),那我們?nèi)绾潍@取setState/useState的最新的值呢?
A.使用setState的最新的值
1、setState方法可以接收兩個(gè)參數(shù),第一個(gè)參數(shù)為一個(gè)對(duì)象,第二個(gè)參數(shù)為一個(gè)函數(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} >點(diǎn)我</button> </div> ) } }
2、使用setTimeout
B.使用useState的最新的值
1、使用另一個(gè)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í)行的同步異步問(wèn)題
只要代碼進(jìn)入了 react調(diào)度流程,那就是異步的。
只要代碼沒(méi)有進(jìn)入 react調(diào)度流程,那就是同步的。
setTimeout、setInterval、async中await的后續(xù)部分,Promise.then(),以及直接在 DOM 上綁定原生事件等。這些都不會(huì)走 React調(diào)度流程,在這種情況下調(diào)用 setState ,那這次 setState 就是同步的。 否則就是異步的。
連續(xù)執(zhí)行兩個(gè) 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)點(diǎn)擊【不受react調(diào)度】按鈕時(shí),render 了兩次 //! 當(dāng)點(diǎn)擊【react調(diào)度】按鈕時(shí),只重新 render 了一次
連續(xù)執(zhí)行兩次同一個(gè) 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)點(diǎn)擊【不受react調(diào)度】按鈕時(shí),兩次 setA 各自 render 一次,分別打印 2,3 //! 當(dāng)點(diǎn)擊【react調(diào)度】按鈕時(shí),兩次 setA 都執(zhí)行,但合并 render 了一次,打印 3
連續(xù)執(zhí)行兩個(gè) 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)點(diǎn)擊【不受react調(diào)度】按鈕時(shí),render 了兩次 //! 當(dāng)點(diǎn)擊【react調(diào)度】按鈕時(shí),只重新 render 了一次
連續(xù)執(zhí)行兩次同一個(gè) 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)點(diǎn)擊【不受react調(diào)度】按鈕時(shí),兩次 setState 各自 render 一次,分別打印 2,3 //! 當(dāng)點(diǎn)擊【react調(diào)度】按鈕時(shí),兩次 setState 合并,只執(zhí)行了最后一次,打印 2
總結(jié)
在正常的react調(diào)度流程中時(shí):
- setState和useState都是異步執(zhí)行的
- 多次執(zhí)行setState和useState,會(huì)進(jìn)行一次batchUpdate,只會(huì)重新渲染render一次
- 不同的是,多次執(zhí)行,setState會(huì)進(jìn)行state的合并,而useState每次運(yùn)行都會(huì)重新計(jì)算
不再react調(diào)度流程中時(shí)
- setState和useState是同步執(zhí)行的(立即更新state,觸發(fā)render,然后繼續(xù)執(zhí)行)
- 多次執(zhí)行setState和useState,每一次的執(zhí)行setState和useState,都會(huì)調(diào)用一次render
到此這篇關(guān)于React中setState/useState的使用方法詳細(xì)介紹的文章就介紹到這了,更多相關(guān)React setState/useState內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
react時(shí)間分片實(shí)現(xiàn)流程詳解
實(shí)現(xiàn)react時(shí)間分片,主要內(nèi)容包括什么是時(shí)間分片、為什么需要時(shí)間分片、實(shí)現(xiàn)分片開(kāi)啟 - 固定、實(shí)現(xiàn)分片中斷、重啟 - 連續(xù)、分片重啟、實(shí)現(xiàn)延遲執(zhí)行 - 有間隔、時(shí)間分片異步執(zhí)行方案的演進(jìn)、時(shí)間分片簡(jiǎn)單實(shí)現(xiàn)、總結(jié)、基本概念、基礎(chǔ)應(yīng)用、原理機(jī)制和需要注意的事項(xiàng)等2022-11-11React 全自動(dòng)數(shù)據(jù)表格組件——BodeGrid的實(shí)現(xiàn)思路
表格是在后臺(tái)管理系統(tǒng)中用的最頻繁的組件之一,相關(guān)的功能有數(shù)據(jù)的新增和編輯、查詢(xún)、排序、分頁(yè)、自定義顯示以及一些操作按鈕。這篇文章主要介紹了React 全自動(dòng)數(shù)據(jù)表格組件——BodeGrid ,需要的朋友可以參考下2019-06-06react國(guó)際化化插件react-i18n-auto使用詳解
這篇文章主要介紹了react國(guó)際化化插件react-i18n-auto使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-03-03