diff --git a/packages/react-reconciler/src/ReactFiberThrow.js b/packages/react-reconciler/src/ReactFiberThrow.js index 94ef5ba8225b6..df2154db9d5cd 100644 --- a/packages/react-reconciler/src/ReactFiberThrow.js +++ b/packages/react-reconciler/src/ReactFiberThrow.js @@ -199,9 +199,11 @@ function throwException( // to render it. let currentSource = sourceFiber.alternate; if (currentSource) { + sourceFiber.updateQueue = currentSource.updateQueue; sourceFiber.memoizedState = currentSource.memoizedState; sourceFiber.expirationTime = currentSource.expirationTime; } else { + sourceFiber.updateQueue = null; sourceFiber.memoizedState = null; } } diff --git a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js index 0df7431977cf2..d3e916fcd8abb 100644 --- a/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js +++ b/packages/react-reconciler/src/__tests__/ReactSuspenseWithNoopRenderer-test.internal.js @@ -1448,6 +1448,53 @@ function loadModules({ 'Caught an error: Error in host config.', ); }); + + it('does not drop mounted effects', async () => { + let never = {then() {}}; + + let setShouldSuspend; + function App() { + const [shouldSuspend, _setShouldSuspend] = React.useState(0); + setShouldSuspend = _setShouldSuspend; + return ( + + + + ); + } + + function Child({shouldSuspend}) { + if (shouldSuspend === 1) { + throw never; + } + + React.useEffect(() => { + Scheduler.unstable_yieldValue('Mount'); + return () => { + Scheduler.unstable_yieldValue('Unmount'); + }; + }, []); + + return 'Child'; + } + + const root = ReactNoop.createLegacyRoot(null); + await ReactNoop.act(async () => { + root.render(); + }); + expect(Scheduler).toHaveYielded(['Mount']); + + // Suspend the child. This puts it into an inconsistent state. + await ReactNoop.act(async () => { + setShouldSuspend(true); + }); + + // Unmount everying + await ReactNoop.act(async () => { + root.render(null); + }); + expect(Scheduler).toHaveYielded(['Unmount']); + }); }); it('does not call lifecycles of a suspended component', async () => {