useEffect(() => { console.log("render"); }); const handleClick = () => { setC1((c) => c + 1); Promise.resolve().then(() => { setC1((c) => c + 1); }); }; const handleClick2 = () => { Promise.resolve().then(() => { setC1((c) => c + 1); }); setC1((c) => c + 1); };
在React18版本中,為什麼點選handleClick
方法會出現兩次渲染,而點選handleClick2
方法只會出現一次渲染?
我希望這兩種方法的輸出是相同的。誰能告訴我為什麼它們不同?
我將解釋這些呼叫順序有何不同,以及觀察到的行為如何可能。
我無法確切地告訴你 React 內部是如何批次更新狀態的, 我只是假設 React 進行了複雜的優化,這與使用 React 的開發人員無關,並且需要深入了解 React 內部,甚至可能從一個版本更改為另一個版本。 (請隨時糾正我。)
#區別
Promise.resolve()
安排一個新的微任務,實際上相當於window.queueMicrotask()
。setState
函數(可能)也會安排新的微任務, 因此它們的回呼(Promise
和setState
)都是在同一執行階段呼叫的。這兩個變體的差別在於
handleClickA
中,在兩個updater
函數之間呼叫setState2
掛鉤,而handleClickB
中,兩個updater
函數都會直接依序呼叫。範例程式碼
我稍微重寫了您的程式碼,以更好地說明呼叫順序:
呼叫順序說明
這裡我說明了呼叫順序。
(FIFO >):
handleClickA
:handleClickB
:個人解讀
我假設 React 嘗試對當前排隊的所有
updater
函數進行批次處理。即只要僅呼叫更新器函數,請嘗試將它們批次在一起並僅更新一次最終狀態。
但是,如果呼叫了新的
setState
函數,React 可能會完成目前更新循環,並在呼叫下一個updater 之前啟動新的渲染週期代码> 函數。
我只能猜測為什麼要這樣做
setState
可能會以某種方式破壞批次處理,或setState
調用,下一次渲染將會延遲太多,或者