欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

react函數(shù)組件useState異步,數(shù)據(jù)不能及時獲取到的問題

 更新時間:2022年08月08日 08:42:13   投稿:jingxian  
這篇文章主要介紹了react函數(shù)組件useState異步,數(shù)據(jù)不能及時獲取到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

react useState異步,數(shù)據(jù)不能獲取到

useState() 屬于異步函數(shù),在useState() 第一次存儲的時候,值會存儲不上

因?yàn)閞eact中state的更新是異步的,我們setState后,react不會立刻對值進(jìn)行改變,而是將其暫時放入pedding隊列中。react會合并多個state,然后值render一次,所以不要在循環(huán)中使用useState,它有可能只render最后一次set值,但是當(dāng)傳入一個函數(shù)時,函數(shù)就會被放入一個隊列中,然后按照順序執(zhí)行。

問題

const Dva = () => {
    const [arr, setArr] = useState([0])
    // 兩個回調(diào)函數(shù),第一個回調(diào)函數(shù)完成后,會將返回結(jié)果作為參數(shù),傳入第二個參數(shù)
    const handleClick = () => {
        Promise.resolve().then(() => {
            setArr([...arr, 1]);
        })
            .then(() => {
                setArr([...arr, 2]);
            })
    }
    useEffect(() => {
        console.log(arr)
    }, [arr]);
    return (
        <>
            <div>
                <button onClick={handleClick}>change</button>
            </div>
        </>
    )
}

輸出:

解決方法一

使用回調(diào)方式傳參

  const handleClick = () => {
        Promise.resolve().then(() => {
            setArr([...arr, 1]);
        }).then(() => {
            setArr(preStae => [...preStae, 2])
        })
    }
    useEffect(() => {
        console.log(arr)
    }, [arr]);

輸出:

react中useState的使用及注意事項(xiàng)

基本使用

useState是 react 提供的一個定義響應(yīng)式變量的 hook 函數(shù),基本語法如下:

const [count, setCount] = useState(initialCount)
  • 它返回一個狀態(tài)和一個修改狀態(tài)的方法,狀態(tài)需要通過這個方法來進(jìn)行修改;
  • initialCount 是我們傳入的一個初始狀態(tài),它是惰性的,我們可以通過傳一個函數(shù)來返回一個值當(dāng)作初始狀態(tài),并且這個函數(shù)只會在初始渲染時執(zhí)行一次;
const [count, setCount] = useState(() => {
    const initialCount = someExpensiveComputation();
    return initialCount
})

接下來把定義好的狀態(tài)運(yùn)用到頁面:

import { useState } from 'react'
function App() {
    const [count, setCount] = useState(0)
    const handleClick = () => {
        setCount(count + 1)
        // 傳入一個函數(shù),更新的值是基于之前的值來執(zhí)行
        // setCount(count => count + 1)
    }
    return (
    	<div>
        	<h4>count: {count}</h4>
            <button onClick={ handleClick }>點(diǎn)擊更新狀態(tài)</button>
        </div>
    )
}

頁面渲染完成后,我們可以看到 count的值是 0,當(dāng)我們點(diǎn)擊按鈕時,會將 count的值加 1,頁面也同時更新;

了解完基礎(chǔ)用法后,我們可以思考幾個問題;

  • setCount修改值時它是同步還是異步?
  • 連續(xù)調(diào)用 setCount會發(fā)生什么?

第一個問題:setCount修改值時它是同步還是異步?

const handleClick = () => {
    console.log("value1: ", count)
    setCount(count => count + 1)
    console.log("value2: ", count)
}

從圖中我們可以看出,頁面的值是更新了,但是控制臺打印的是之前的值,這是不是也表示 setCount是異步的呢?我們換一種方法,用異步來修改狀態(tài);

const handleClick = () => {
    console.log("value1: ", count)
    setTimeout(() => {
        setCount(count => count + 1)
        console.log("value2: ", count)
    }, 0)
}

顯然,異步修改狀態(tài)跟同步修改狀態(tài)的結(jié)果是一致的,這也表明了 setCount 是異步更新的;那我們要怎么拿到更新后的值呢,我們可以用另外一個 hook 函數(shù) useRef,代碼如下:

function App() {
  const [count, setCount] = useState(0)
  const countRef = useRef(count)
  countRef.current = count
  const handleClick = () => {
    setCount(count => count + 1)
    console.log("value3: ", count)
    setTimeout(() => {
      console.log(countRef.current)
    }, 0)
  }
  return (
    <div>
      <h4>count: {count}</h4>
      <button onClick={handleClick}>點(diǎn)擊更新狀態(tài)</button>
    </div>
  )
}

從圖中我們可以看出,我們已經(jīng)拿到了更新之后的值,useRef不僅可以用于訪問 DOM 節(jié)點(diǎn),也可以用來表示一個容器,current屬性可以保存任何值,而且useRef返回的對象會在整個生命周期內(nèi)保持;

第二個問題:連續(xù)調(diào)用 setCount會發(fā)生什么?

(1)傳入一個基于狀態(tài)的值

const handleClick = () => {
    console.log("value1: ", count)
    setCount(count + 1)
    console.log("value2: ", count)
    setCount(count + 1)
    console.log("value3: ", count)
}

從圖片可以看出,如果我們傳入的是一個普通值,他只會進(jìn)行最后一次更新;

(2)傳入一個函數(shù)

const handleClick = () => {
    console.log("value1: ", count)
    setCount(count => count + 1)
    console.log("value2: ", count)
    setCount(count => count + 1)
    console.log("value3: ", count)
}

可以看出,傳入一個函數(shù)的話,它會進(jìn)行兩次賦值,因?yàn)樗碌闹凳腔谥暗闹祦韴?zhí)行,所以在開發(fā)中推薦使用函數(shù)傳入的形式進(jìn)行修改;

注意事項(xiàng)

1、復(fù)雜變量的修改

對于復(fù)雜類型的變量我們修改時需要重新定義,在原來數(shù)據(jù)的基礎(chǔ)上修改不會引起組件的重新渲染,因?yàn)?React 組件的更新機(jī)制只進(jìn)行淺對比,也就是更新某個復(fù)雜類型數(shù)據(jù)時只要它的引用地址沒變,就不會重新渲染組件;舉個例子

function App() {
    const [arr, setArr] = useState([1])
    const pushData = () => {
        arr.push(4)
        setArr(arr)
    }
    return (
        <div>
            <h4>{arr.join("-")}</h4>
            <button onClick={pushData}>點(diǎn)擊添加數(shù)組</button>
        </div>
    )
}

上面的代碼在點(diǎn)擊按鈕時,視圖不會發(fā)生變化,但是 arr的值是變化了,如果想修改這個數(shù)組,需要重新定義一個數(shù)組來修改,在原數(shù)組上的修改不會引起組件的重新渲染,React 組件的更新機(jī)制對只進(jìn)行淺對比,也就是更新某個復(fù)雜類型數(shù)據(jù)時只要它的引用地址沒變,就不會重新渲染組件;

const pushData = () => {
    setArr([...arr, 4])
}

2、異步操作獲取更新的值

在類組件里面,修改值時異步操作可以拿到更新后的值,但是在函數(shù)組件,異步獲取是拿不到更新后的值的,舉個例子對比一下:

類組件

class App extends React.Component {
    constructor() {
        super()
        this.state = {
            count: 0
        }
    }
    handleClick = () => {
        this.setState({
            count: this.state.count + 1
        })
        console.log(this.state.count)
        setTimeout(() => {
            console.log(this.state.count)
        })
    }
    render() {
        return (
            <>
            <h4>count: {this.state.count}</h4>
            <button onClick={this.handleClick}>點(diǎn)擊更新狀態(tài)</button>
            </>
        );
    }
}

函數(shù)組件

function App() {
    const [count, setCount] = useState(0)
    const handleClick = () => {
        setCount(count => count + 1)
        console.log("value1: ", count)
        setTimeout(() => {
            console.log("value2: ", count)
        })
    }
    return (
        <div>
            <h4>count: {count}</h4>
            <button onClick={handleClick}>點(diǎn)擊更新狀態(tài)</button>
        </div>
    )
}

顯然,在函數(shù)組件中是不能通過異步來獲取更新的值,我們可以通過 useRef來獲取;

const countRef = useRef(count)
countRef.current = count
const handleClick = () => {
    setCount(count => count + 1)
    console.log("value1: ", countRef.current)
    setTimeout(() => {
        console.log("value2: ", countRef.current)
    })
}

以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • 深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐

    深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐

    這篇文章主要介紹了深入學(xué)習(xí)TypeScript 、React、 Redux和Ant-Design的最佳實(shí)踐,TypeScript 增加了代碼的可讀性和可維護(hù)性,擁有活躍的社區(qū),,需要的朋友可以參考下
    2019-06-06
  • React18新增特性介紹

    React18新增特性介紹

    react歷次版本迭代主要想解決的是兩類導(dǎo)致網(wǎng)頁卡頓的問題,分別是cpu密集型任務(wù)和io密集型任務(wù)導(dǎo)致的卡頓問題,react18新增特性就是為了解決上述問題
    2022-09-09
  • React中使用async validator進(jìn)行表單驗(yàn)證的實(shí)例代碼

    React中使用async validator進(jìn)行表單驗(yàn)證的實(shí)例代碼

    react上進(jìn)行表單驗(yàn)證是很繁瑣的,在這里使用async-validator處理起來就變的很方便了,接下來通過本文給大家介紹React中使用async validator進(jìn)行表單驗(yàn)證的方法,需要的朋友可以參考下
    2018-08-08
  • React?less?實(shí)現(xiàn)縱橫柱狀圖示例詳解

    React?less?實(shí)現(xiàn)縱橫柱狀圖示例詳解

    這篇文章主要介紹了React?less?實(shí)現(xiàn)縱橫柱狀圖示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 淺談使用React.setState需要注意的三點(diǎn)

    淺談使用React.setState需要注意的三點(diǎn)

    本篇文章主要介紹了淺談使用React.setState需要注意的三點(diǎn),提出了三點(diǎn)對 React 新手來說是很容易忽略的地方,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • react基于react-slick實(shí)現(xiàn)多圖輪播效果

    react基于react-slick實(shí)現(xiàn)多圖輪播效果

    React slick是一個使用React構(gòu)建的輪播組件,下面這篇文章主要給大家介紹了關(guān)于react基于react-slick實(shí)現(xiàn)多圖輪播效果的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • 基于visual studio code + react 開發(fā)環(huán)境搭建過程

    基于visual studio code + react 開發(fā)環(huán)境搭建過程

    今天通過本文給大家分享基于visual studio code + react 開發(fā)環(huán)境搭建過程,本文給大家介紹的非常詳細(xì),包括react安裝問題及安裝 Debugger for Chrome的方法,需要的朋友跟隨小編一起看看吧
    2021-07-07
  • React Hooks的深入理解與使用

    React Hooks的深入理解與使用

    這篇文章主要介紹了React Hooks的深入理解與使用,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11
  • 詳解react阻止無效重渲染的多種方式

    詳解react阻止無效重渲染的多種方式

    這篇文章主要介紹了詳解react阻止無效重渲染的多種方式,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-12-12
  • react中axios結(jié)合后端實(shí)現(xiàn)GET和POST請求方式

    react中axios結(jié)合后端實(shí)現(xiàn)GET和POST請求方式

    這篇文章主要介紹了react中axios結(jié)合后端實(shí)現(xiàn)GET和POST請求方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02

最新評論