diff --git a/packages/react-reconciler/src/ReactUpdateQueue.js b/packages/react-reconciler/src/ReactUpdateQueue.js index 3938a95b1188e..7376e216d5804 100644 --- a/packages/react-reconciler/src/ReactUpdateQueue.js +++ b/packages/react-reconciler/src/ReactUpdateQueue.js @@ -122,7 +122,10 @@ export type UpdateQueue = { firstEffect: Update | null, lastEffect: Update | null, - // TODO: Workaround for lack of tuples. Could global state instead. + firstCapturedEffect: Update | null, + lastCapturedEffect: Update | null, + + // TODO: Workaround for lack of tuples. Could use global state instead. hasForceUpdate: boolean, // DEV-only @@ -144,6 +147,8 @@ export function createUpdateQueue(baseState: State): UpdateQueue { lastCapturedUpdate: null, firstEffect: null, lastEffect: null, + firstCapturedEffect: null, + lastCapturedEffect: null, hasForceUpdate: false, }; if (__DEV__) { @@ -170,6 +175,9 @@ function cloneUpdateQueue( firstEffect: null, lastEffect: null, + + firstCapturedEffect: null, + lastCapturedEffect: null, }; if (__DEV__) { queue.isProcessing = false; @@ -330,39 +338,6 @@ export function enqueueCapturedUpdate( } } -function addToEffectList( - queue: UpdateQueue, - update: Update, -) { - // Set this to null, in case it was mutated during an aborted render. - update.nextEffect = null; - if (queue.lastEffect === null) { - queue.firstEffect = queue.lastEffect = update; - } else { - queue.lastEffect.nextEffect = update; - queue.lastEffect = update; - } -} - -function processSingleUpdate( - workInProgress: Fiber, - queue: UpdateQueue, - update: Update, - prevState: State, -): State { - const commit = update.commit; - const process = update.process; - if (commit !== null) { - workInProgress.effectTag |= Callback; - addToEffectList(queue, update); - } - if (process !== null) { - return process(workInProgress, prevState, queue); - } else { - return prevState; - } -} - function ensureWorkInProgressQueueIsAClone( workInProgress: Fiber, queue: UpdateQueue, @@ -428,12 +403,22 @@ export function processUpdateQueue( } else { // This update does have sufficient priority. Process it and compute // a new result. - resultState = processSingleUpdate( - workInProgress, - queue, - update, - resultState, - ); + const commit = update.commit; + const process = update.process; + if (process !== null) { + resultState = process(workInProgress, resultState, queue); + } + if (commit !== null) { + workInProgress.effectTag |= Callback; + // Set this to null, in case it was mutated during an aborted render. + update.nextEffect = null; + if (queue.lastEffect === null) { + queue.firstEffect = queue.lastEffect = update; + } else { + queue.lastEffect.nextEffect = update; + queue.lastEffect = update; + } + } } // Continue to the next update. update = update.next; @@ -467,12 +452,22 @@ export function processUpdateQueue( } else { // This update does have sufficient priority. Process it and compute // a new result. - resultState = processSingleUpdate( - workInProgress, - queue, - update, - resultState, - ); + const commit = update.commit; + const process = update.process; + if (process !== null) { + resultState = process(workInProgress, resultState, queue); + } + if (commit !== null) { + workInProgress.effectTag |= Callback; + // Set this to null, in case it was mutated during an aborted render. + update.nextEffect = null; + if (queue.lastCapturedEffect === null) { + queue.firstCapturedEffect = queue.lastCapturedEffect = update; + } else { + queue.lastCapturedEffect.nextEffect = update; + queue.lastCapturedEffect = update; + } + } } update = update.next; } @@ -533,4 +528,15 @@ export function commitUpdateQueue( } effect = effect.nextEffect; } + + effect = finishedQueue.firstCapturedEffect; + finishedQueue.firstCapturedEffect = finishedQueue.lastCapturedEffect = null; + while (effect !== null) { + const commit = effect.commit; + if (commit !== null) { + effect.commit = null; + commit(finishedWork); + } + effect = effect.nextEffect; + } }