@@ -496,4 +496,82 @@ describe('ReactSuspenseEffectsSemanticsDOM', () => {
496
496
ReactDOM . render ( null , container ) ;
497
497
assertLog ( [ 'Unmount' ] ) ;
498
498
} ) ;
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
+ } ) ;
499
577
} ) ;
0 commit comments