diff --git a/packages/react-reconciler/src/ReactUpdateQueue.js b/packages/react-reconciler/src/ReactUpdateQueue.js index 3938a95b1188e..2e5b2c626e01b 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; @@ -428,12 +436,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 +485,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 +561,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; + } }