{setC1((c)=>c+1);Promise.resolve().then(()=>{setC1((c)=>c+1);});};consthandleClick2=()=>{Promise.resolve().then"> React18微任務批次問題-PHP中文網路問答
React18微任務批次問題
P粉506963842
P粉506963842 2023-09-07 22:30:24
0
1
419

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方法只會出現一次渲染?

我希望這兩種方法的輸出是相同的。誰能告訴我為什麼它們不同?

P粉506963842
P粉506963842

全部回覆 (1)
P粉642920522

我將解釋這些呼叫順序有何不同,以及觀察到的行為如何可能。

我無法確切地告訴你 React 內部是如何批次更新狀態的, 我只是假設 React 進行了複雜的優化,這與使用 React 的開發人員無關,並且需要深入了解 React 內部,甚至可能從一個版本更改為另一個版本。(請隨時糾正我。)

#區別

Promise.resolve()安排一個新的微任務,實際上相當於window.queueMicrotask()

setState函數(可能)也會安排新的微任務, 因此它們的回呼(PromisesetState)都是在同一執行階段呼叫的。

這兩個變體的差別在於

  • handleClickA中,在兩個updater函數之間呼叫setState2掛鉤,而
  • handleClickB中,兩個updater函數都會直接依序呼叫。

範例程式碼

我稍微重寫了您的程式碼,以更好地說明呼叫順序:

const setState1 = setState; const setState2 = setState; const update1 = updaterFunction; // c => c + 1 const update2 = updaterFunction; // c => c + 1 const handleClickA = () => { // Scheduled functions: setState1( update1 ); // 1. --> [ update1 ] queueMicrotask(() => { // 2. --> [ update1, setState2 ] setState2( update2 ); // 4. --> [ update2 ] }); // update1(); // 3. --> [ setState2 ] // setState2( update2 ); // 4. --> [ update2 ] // update2(); // 5. --> [] }; const handleClickB = () => { // Scheduled functions: queueMicrotask(() => { // 1. --> [ setState2 ] setState2( update2 ); // 3. --> [ update2 ] }); setState1( update1 ); // 2. --> [ setState2, update1 ] // setState2( update2 ); // 3. --> [ update1, update2 ] // update1(); // 4. --> [ update2 ] // update2(); // 5. --> [] };

呼叫順序說明

這裡我說明了呼叫順序。

(FIFO>):

handleClickA

// 0. --> [] - schedule update1 (setState1()) // 1. --> [ update1 ] - schedule setState2 // 2. --> [ update1, setState2 ] - invoke update1() // 3. --> [ setState2 ] - schedule update2 (setState2()) // 4. --> [ update2 ] - invoke update2() // 5. --> []

handleClickB

// 0. --> [] schedule setState2 // 1. --> [ setState2 ] schedule update1 (setState1()) // 2. --> [ setState2, update1 ] schedule update2 (setState2()) // 3. --> [ update1, update2 ] invoke update1() // 4. --> [ update2 ] invoke update2() // 5. --> []

個人解讀

我假設 React 嘗試對當前排隊的所有updater函數進行批次處理。

即只要僅呼叫更新器函數,請嘗試將它們批次在一起僅更新一次最終狀態。

但是,如果呼叫了新的setState函數,React 可能會完成目前更新循環,並在呼叫下一個updater 之前啟動新的渲染週期代码> 函數。

我只能猜測為什麼要這樣做

  • 因為新的setState可能會以某種方式破壞批次處理,或
  • 如果遞歸調用新的setState調用,下一次渲染將會延遲太多,或者
  • React 人員仍在研究最佳優化策略及其權衡。
  • (...或這是一個錯誤。)
    最新下載
    更多>
    網站特效
    網站源碼
    網站素材
    前端模板
    關於我們 免責聲明 Sitemap
    PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!