簡體   English   中英

為什么調用 set function 的 useState 鈎子會立即應用於異步函數?

[英]Why calling set function of useState hook applies immediately in async functions?

在同步和異步 function 中調用 useState 鈎子的多個集合函數時,我遇到了不同的行為。

function Test() {
    console.log('app rendering starts.');
    const [a, setA] = useState(1);
    const [b, setB] = useState(11);
    const updateState = () => {
        console.log('\tupdating a starts.');
        setA(2);
        console.log('\tupdating a ends.');
        console.log('\tupdating b starts.');
        setB(12);
        console.log('\tupdating b ends.');
    };
    console.log('app rendering ends.');
    return (
        <div className="App">
            <div>a is {a}</div>
            <div>b is {b}</div>
            <button onClick={() => {
                console.log('--------------sync click--------------');
                updateState();
            }}>Update State a & b Sync</button>
            <button onClick={() => {
                console.log('--------------async click--------------');
                setTimeout(updateState, 0)
            }}>Update State a & b Async</button>
        </div>
    );
}

兩個按鈕執行相同的代碼,但方式不同。
同步按鈕結果:

app rendering starts.
app rendering ends.
--------------sync click--------------
    updating a starts.
    updating a ends.
    updating b starts.
    updating b ends.
app rendering starts.
app rendering ends.

異步按鈕結果:

app rendering starts.
app rendering ends.
--------------async click--------------
    updating a starts.
app rendering starts.
app rendering ends.
    updating a ends.
    updating b starts.
app rendering starts.
app rendering ends.
    updating b ends.

這是理想的行為嗎?
如何在異步 function 中獲得同步結果?
我在官方文檔中找不到任何提示。
任何幫助,將不勝感激。
謝謝!

根據Github 討論,這似乎是一個已知事實。

我認為其中一條評論非常不言自明:

如果 state 更新是從基於 React 的事件中觸發的,例如按鈕單擊或輸入更改,React 當前將批量更新。 如果它們是在 React 事件處理程序之外觸發的,它不會批量更新,比如 setTimeout()。

您可以使用unstable_batchedUpdates的批處理更新(來自 ReactDOM)來獲得您期望的行為。

import { unstable_batchedUpdates } from "react-dom";
const updateState = () => {
    unstable_batchedUpdates(() => {
      console.log("\tupdating a starts.");
      setA(2);
      console.log("\tupdating a ends.");
      console.log("\tupdating b starts.");
      setB(12);
      console.log("\tupdating b ends.");
    });
  };

沙盒鏈接

您可以使用單個useState()useReducer()掛鈎調用來更新多個 state 值,方法是將它們存儲在一起,而不是將其存儲在單獨的 state 切片中。

const [values, setValues] = useState({a: 1, b: 11});

setValues({a: 2, b: 12});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM