mirror of
https://github.com/facebook/react.git
synced 2025-11-01 09:12:30 +00:00
Schedule passive callbacks before layout effects are invoked (#16713)
This commit is contained in:
+11
-12
@@ -1497,14 +1497,6 @@ function commitRoot(root) {
|
||||
ImmediatePriority,
|
||||
commitRootImpl.bind(null, root, renderPriorityLevel),
|
||||
);
|
||||
// If there are passive effects, schedule a callback to flush them. This goes
|
||||
// outside commitRootImpl so that it inherits the priority of the render.
|
||||
if (rootWithPendingPassiveEffects !== null) {
|
||||
scheduleCallback(NormalPriority, () => {
|
||||
flushPassiveEffects();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1858,6 +1850,17 @@ function commitMutationEffects(root: FiberRoot, renderPriorityLevel) {
|
||||
}
|
||||
}
|
||||
|
||||
if (effectTag & Passive) {
|
||||
// If there are passive effects, schedule a callback to flush them.
|
||||
if (!rootDoesHavePassiveEffects) {
|
||||
rootDoesHavePassiveEffects = true;
|
||||
scheduleCallback(NormalPriority, () => {
|
||||
flushPassiveEffects();
|
||||
return null;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// The following switch statement is only concerned about placement,
|
||||
// updates, and deletions. To avoid needing to add a case for every possible
|
||||
// bitmap value, we remove the secondary effects from the effect tag and
|
||||
@@ -1943,10 +1946,6 @@ function commitLayoutEffects(
|
||||
commitAttachRef(nextEffect);
|
||||
}
|
||||
|
||||
if (effectTag & Passive) {
|
||||
rootDoesHavePassiveEffects = true;
|
||||
}
|
||||
|
||||
resetCurrentDebugFiberInDEV();
|
||||
nextEffect = nextEffect.nextEffect;
|
||||
}
|
||||
|
||||
@@ -265,6 +265,33 @@ describe('ReactSchedulerIntegration', () => {
|
||||
expect(Scheduler).toHaveYielded(['Effect clean-up priority: Idle']);
|
||||
});
|
||||
|
||||
it('passive effects are called before Normal-pri scheduled in layout effects', async () => {
|
||||
const {useEffect, useLayoutEffect} = React;
|
||||
function Effects({step}) {
|
||||
useLayoutEffect(() => {
|
||||
Scheduler.unstable_yieldValue('Layout Effect');
|
||||
Scheduler.unstable_scheduleCallback(NormalPriority, () =>
|
||||
Scheduler.unstable_yieldValue(
|
||||
'Scheduled Normal Callback from Layout Effect',
|
||||
),
|
||||
);
|
||||
});
|
||||
useEffect(() => {
|
||||
Scheduler.unstable_yieldValue('Passive Effect');
|
||||
});
|
||||
return null;
|
||||
}
|
||||
await ReactNoop.act(async () => {
|
||||
ReactNoop.render(<Effects />);
|
||||
});
|
||||
expect(Scheduler).toHaveYielded([
|
||||
'Layout Effect',
|
||||
'Passive Effect',
|
||||
// This callback should be scheduled after the passive effects.
|
||||
'Scheduled Normal Callback from Layout Effect',
|
||||
]);
|
||||
});
|
||||
|
||||
it('after completing a level of work, infers priority of the next batch based on its expiration time', () => {
|
||||
function App({label}) {
|
||||
Scheduler.unstable_yieldValue(
|
||||
|
||||
Reference in New Issue
Block a user