diff --git a/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js b/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js index c9e66fe0399e..153d4d28bd3f 100644 --- a/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js +++ b/packages/react-reconciler/src/__tests__/ReactInterleavedUpdates-test.js @@ -140,4 +140,52 @@ describe('ReactInterleavedUpdates', () => { expect(Scheduler).toHaveYielded([2, 2, 2]); expect(root).toMatchRenderedOutput('222'); }); + + test('regression for #24350: does not add to main update queue until interleaved update queue has been cleared', async () => { + let setStep; + function App() { + const [step, _setState] = useState(0); + setStep = _setState; + return ( + <> + + + + + ); + } + + const root = ReactNoop.createRoot(); + await act(async () => { + root.render(); + }); + expect(Scheduler).toHaveYielded(['A0', 'B0', 'C0']); + expect(root).toMatchRenderedOutput('A0B0C0'); + + await act(async () => { + // Start the render phase. + startTransition(() => { + setStep(1); + }); + expect(Scheduler).toFlushAndYieldThrough(['A1', 'B1']); + + // Schedule an interleaved update. This gets placed on a special queue. + startTransition(() => { + setStep(2); + }); + + // Finish rendering the first update. + expect(Scheduler).toFlushUntilNextPaint(['C1']); + + // Schedule another update. (In the regression case, this was treated + // as a normal, non-interleaved update and it was inserted into the queue + // before the interleaved one was processed.) + startTransition(() => { + setStep(3); + }); + }); + // The last update should win. + expect(Scheduler).toHaveYielded(['A3', 'B3', 'C3']); + expect(root).toMatchRenderedOutput('A3B3C3'); + }); });