在同步和異步函式中呼叫 useState hook 的多個 set 函式時,我遇到了不同的行為。
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.
這是一種理想的行為嗎?
如何在異步函式中獲得同步結果?
我在官方檔案中找不到任何關于此的提示。
任何幫助,將不勝感激。
謝謝!
uj5u.com熱心網友回復:
根據Github 的討論,這似乎是一個眾所周知的事實。
評論之一,我認為這是不言自明的:
如果從基于 React 的事件中觸發狀態更新,例如按鈕單擊或輸入更改,React 當前將批處理狀態更新。如果在 React 事件處理程式之外觸發更新,則不會批量更新,例如 setTimeout()。
React 內部使用unstable_batchedUpdates(). 您可以傳入一個回呼函式并在其中進行狀態更新以進行批處理。對于超時、承諾和異步函式,這不會自動發生。所以它們是從回呼外部呼叫的,并且它們內部的狀態更新不會被批處理。
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.");
});
};
沙盒鏈接
uj5u.com熱心網友回復:
您可以使用單個useState()或useReducer()鉤子呼叫通過將它們存盤在一起而不是將其存盤在單獨的狀態切片中來更新多個狀態值。
const [values, setValues] = useState({a: 1, b: 11});
setValues({a: 2, b: 12});
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/368349.html
標籤:javascript 反应 反应钩子
上一篇:本地存盤未在Next.js中定義
