diff --git a/packages/react-reconciler/src/ReactFiberClassComponent.js b/packages/react-reconciler/src/ReactFiberClassComponent.js index b2b50a6a52..9a167e6f4c 100644 --- a/packages/react-reconciler/src/ReactFiberClassComponent.js +++ b/packages/react-reconciler/src/ReactFiberClassComponent.js @@ -51,7 +51,7 @@ import { requestCurrentTime, computeExpirationForFiber, scheduleWork, - flushPassiveEffectsBeforeSchedulingUpdateOnFiber, + flushPassiveEffects, } from './ReactFiberScheduler'; const ReactCurrentOwner = ReactSharedInternals.ReactCurrentOwner; @@ -200,7 +200,7 @@ const classComponentUpdater = { update.callback = callback; } - flushPassiveEffectsBeforeSchedulingUpdateOnFiber(fiber); + flushPassiveEffects(); enqueueUpdate(fiber, update); scheduleWork(fiber, expirationTime); }, @@ -220,7 +220,7 @@ const classComponentUpdater = { update.callback = callback; } - flushPassiveEffectsBeforeSchedulingUpdateOnFiber(fiber); + flushPassiveEffects(); enqueueUpdate(fiber, update); scheduleWork(fiber, expirationTime); }, @@ -239,7 +239,7 @@ const classComponentUpdater = { update.callback = callback; } - flushPassiveEffectsBeforeSchedulingUpdateOnFiber(fiber); + flushPassiveEffects(); enqueueUpdate(fiber, update); scheduleWork(fiber, expirationTime); }, diff --git a/packages/react-reconciler/src/ReactFiberCommitWork.js b/packages/react-reconciler/src/ReactFiberCommitWork.js index 3f61066dd9..2f76b6ff50 100644 --- a/packages/react-reconciler/src/ReactFiberCommitWork.js +++ b/packages/react-reconciler/src/ReactFiberCommitWork.js @@ -85,7 +85,7 @@ import { } from './ReactFiberHostConfig'; import { captureCommitPhaseError, - flushPassiveEffectsBeforeSchedulingUpdateOnFiber, + flushPassiveEffects, requestCurrentTime, scheduleWork, } from './ReactFiberScheduler'; @@ -457,7 +457,7 @@ function commitLifeCycles( timedOutAt: NoWork, }; finishedWork.memoizedState = newState; - flushPassiveEffectsBeforeSchedulingUpdateOnFiber(finishedWork); + flushPassiveEffects(); scheduleWork(finishedWork, Sync); return; } diff --git a/packages/react-reconciler/src/ReactFiberHooks.js b/packages/react-reconciler/src/ReactFiberHooks.js index 5e843c5e53..eef5c602b0 100644 --- a/packages/react-reconciler/src/ReactFiberHooks.js +++ b/packages/react-reconciler/src/ReactFiberHooks.js @@ -32,7 +32,7 @@ import { import { scheduleWork, computeExpirationForFiber, - flushPassiveEffectsBeforeSchedulingUpdateOnFiber, + flushPassiveEffects, requestCurrentTime, } from './ReactFiberScheduler'; @@ -725,7 +725,7 @@ function dispatchAction( callback: callback !== undefined ? callback : null, next: null, }; - flushPassiveEffectsBeforeSchedulingUpdateOnFiber(fiber); + flushPassiveEffects(); // Append the update to the end of the list. const last = queue.last; if (last === null) { diff --git a/packages/react-reconciler/src/ReactFiberReconciler.js b/packages/react-reconciler/src/ReactFiberReconciler.js index b06922c94f..a61c1a3304 100644 --- a/packages/react-reconciler/src/ReactFiberReconciler.js +++ b/packages/react-reconciler/src/ReactFiberReconciler.js @@ -52,7 +52,7 @@ import { syncUpdates, interactiveUpdates, flushInteractiveUpdates, - flushPassiveEffectsBeforeSchedulingUpdateOnFiber, + flushPassiveEffects, } from './ReactFiberScheduler'; import {createUpdate, enqueueUpdate} from './ReactUpdateQueue'; import ReactFiberInstrumentation from './ReactFiberInstrumentation'; @@ -147,7 +147,7 @@ function scheduleRootUpdate( update.callback = callback; } - flushPassiveEffectsBeforeSchedulingUpdateOnFiber(current); + flushPassiveEffects(); enqueueUpdate(current, update); scheduleWork(current, expirationTime); diff --git a/packages/react-reconciler/src/ReactFiberScheduler.js b/packages/react-reconciler/src/ReactFiberScheduler.js index 21a919b5c5..b49715971f 100644 --- a/packages/react-reconciler/src/ReactFiberScheduler.js +++ b/packages/react-reconciler/src/ReactFiberScheduler.js @@ -578,33 +578,8 @@ function markLegacyErrorBoundaryAsFailed(instance: mixed) { } } -function flushPassiveEffectsBeforeSchedulingUpdateOnFiber(fiber: Fiber) { - if (rootWithPendingPassiveEffects !== null) { - // TODO: This is an unfortunate extra loop. We end up traversing to the root - // again in scheduleWorkToRoot. But we have to do this one first because it - // needs to happen before adding an update to the queue, and - // scheduleWorkToRoot may perform a synchronous re-render. Maybe we can - // solve this with batchedUpdates, or with the equivalent in the Scheduler - // package. - let node = fiber; - do { - switch (node.tag) { - case HostRoot: { - const root: FiberRoot = node.stateNode; - flushPassiveEffects(root); - return; - } - } - node = node.return; - } while (node !== null); - } -} - -function flushPassiveEffects(root: FiberRoot) { - if ( - passiveEffectCallback !== null && - root === rootWithPendingPassiveEffects - ) { +function flushPassiveEffects() { + if (passiveEffectCallback !== null) { Schedule_cancelCallback(passiveEffectCallbackHandle); // We call the scheduled callback instead of commitPassiveEffects directly // to ensure tracing works correctly. @@ -1248,7 +1223,7 @@ function renderRoot( 'by a bug in React. Please file an issue.', ); - flushPassiveEffects(root); + flushPassiveEffects(); isWorking = true; ReactCurrentOwner.currentDispatcher = Dispatcher; @@ -2613,5 +2588,5 @@ export { interactiveUpdates, flushInteractiveUpdates, computeUniqueAsyncExpiration, - flushPassiveEffectsBeforeSchedulingUpdateOnFiber, + flushPassiveEffects, }; diff --git a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js index 22ce1bc4e4..0c38e61559 100644 --- a/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactHooks-test.internal.js @@ -717,6 +717,35 @@ describe('ReactHooks', () => { ]); }); + it('flushes passive effects even if siblings schedule a new root', () => { + function PassiveEffect(props) { + useEffect(() => { + ReactNoop.yield('Passive effect'); + }, []); + return ; + } + function LayoutEffect(props) { + useLayoutEffect(() => { + ReactNoop.yield('Layout effect'); + // Scheduling work shouldn't interfere with the queued passive effect + ReactNoop.renderToRootWithID(, 'root2'); + }); + return ; + } + ReactNoop.render([, ]); + expect(ReactNoop.flush()).toEqual([ + 'Passive', + 'Layout', + 'Layout effect', + 'Passive effect', + 'New Root', + ]); + expect(ReactNoop.getChildren()).toEqual([ + span('Passive'), + span('Layout'), + ]); + }); + it( 'flushes effects serially by flushing old effects before flushing ' + "new ones, if they haven't already fired",