Skip to content

Commit 850b4b1

Browse files
committed
Failing test: does not call cleanup effects twice after a bailout
1 parent 4a1cc2d commit 850b4b1

File tree

1 file changed

+78
-0
lines changed

1 file changed

+78
-0
lines changed

packages/react-reconciler/src/__tests__/ReactSuspenseEffectsSemanticsDOM-test.js

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -496,4 +496,82 @@ describe('ReactSuspenseEffectsSemanticsDOM', () => {
496496
ReactDOM.render(null, container);
497497
assertLog(['Unmount']);
498498
});
499+
500+
it('does not call cleanup effects twice after a bailout', async () => {
501+
const never = new Promise(resolve => {});
502+
function Never() {
503+
throw never;
504+
}
505+
506+
let setSuspended;
507+
let setLetter;
508+
509+
function App() {
510+
const [suspended, _setSuspended] = React.useState(false);
511+
setSuspended = _setSuspended;
512+
const [letter, _setLetter] = React.useState('A');
513+
setLetter = _setLetter;
514+
515+
return (
516+
<React.Suspense fallback="Loading...">
517+
<Child letter={letter} />
518+
{suspended && <Never />}
519+
</React.Suspense>
520+
);
521+
}
522+
523+
let nextId = 0;
524+
const freed = new Set();
525+
let setStep;
526+
527+
function Child({letter}) {
528+
const [, _setStep] = React.useState(0);
529+
setStep = _setStep;
530+
531+
React.useLayoutEffect(() => {
532+
const localId = nextId++;
533+
Scheduler.log('Did mount: ' + letter + localId);
534+
return () => {
535+
if (freed.has(localId)) {
536+
throw Error('Double free: ' + letter + localId);
537+
}
538+
freed.add(localId);
539+
Scheduler.log('Will unmount: ' + letter + localId);
540+
};
541+
}, [letter]);
542+
}
543+
544+
const root = ReactDOMClient.createRoot(container);
545+
await act(() => {
546+
root.render(<App />);
547+
});
548+
assertLog(['Did mount: A0']);
549+
550+
await act(() => {
551+
setStep(1);
552+
setSuspended(false);
553+
});
554+
assertLog([]);
555+
556+
await act(() => {
557+
setStep(1);
558+
});
559+
assertLog([]);
560+
561+
await act(() => {
562+
setSuspended(true);
563+
});
564+
assertLog(['Will unmount: A0']);
565+
566+
await act(() => {
567+
setSuspended(false);
568+
setLetter('B');
569+
});
570+
assertLog(['Did mount: B1']);
571+
572+
await act(() => {
573+
root.unmount();
574+
});
575+
assertLog(['Will unmount: B1']);
576+
});
499577
});

0 commit comments

Comments
 (0)