Schedule passive callbacks before layout effects are invoked (#16713)

This commit is contained in:
Sebastian Markbåge
2019-09-09 13:34:57 -07:00
committed by GitHub
parent 031eba789f
commit cc2492ccf1
2 changed files with 38 additions and 12 deletions
+11 -12
View File
@@ -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(