React Hook 中 useState 異步回調(diào)獲取不到最新值及解決方案

異常代碼

import React, { useState, useEffect } from 'react';

const App = () => {
  const [arr, setArr] = useState([0]);

  useEffect(() => {
    console.log(arr);
  }, [arr]);

  const handleClick = () => {
    Promise.resolve().then(() => {
      setArr([...arr, 1]); // 此時賦值前 arr 為:[0]
    })
      .then(() => {
        setArr([...arr, 2]); // 此時賦值前 arr 為舊狀態(tài)仍然為:[0]
      });
  }

  return (
    <>
      <button onClick={handleClick}>change</button>
    </>
  );
}

export default App;

上面代碼,App 組件實際也是個閉包函數(shù),handleClick 里面引用著 arr,第一次 setArr 后 arr 的值確實更新了,我們也可以在下面截圖中看到,但此時 handleClick 事件處理函數(shù)作用域還是舊的,里面引用的 arr 仍然為舊的,導(dǎo)致第二次 setArr 后結(jié)果為 [0, 2]:

解決方案一

將上述代碼使用第二種(回調(diào))方式傳參

const handleClick = () => {
    Promise.resolve().then(() => {
      setArr(prevState => [...prevState, 1]); // 這里也可以不改,使用 setArr([...arr, 1]); 因為這里不需要獲取最新狀態(tài)
    })
      .then(() => {
        setArr(prevState => [...prevState, 2]); // 這里必須改成回調(diào)函數(shù)傳參方式,否則會讀取舊狀態(tài),導(dǎo)致異常
      });
  }

解決方案二

利用 ref

import React, { useState, useRef, useEffect } from 'react';

const App = () => {
  const [arr, setArr] = useState([0]);
  let ref = useRef();
  useEffect(() => {
    ref.current = arr;
    console.log(arr);
  });

  const handleClick = () => {
    Promise.resolve().then(() => {
      const now = [...ref.current, 1];
      ref.current = now;
      setArr(now);
    })
      .then(() => {
        setArr([...ref.current, 2]);
      });
  }

  return (
    <>
      <h1>{arr.toString()}</h1>
      <button onClick={handleClick}>change</button>
    </>
  );
}

export default App;

官網(wǎng)中的一段話:如果你刻意地想要從某些異步回調(diào)中讀取 最新的 state,你可以用 一個 ref 來保存它,修改它,并從中讀取。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容