@@ -412,6 +412,87 @@ describe('FragmentRefs', () => {
412
412
expect ( logs ) . toEqual ( [ 'Host A' , 'Host B' ] ) ;
413
413
} ) ;
414
414
415
+ // @gate enableFragmentRefs
416
+ it ( 'allows adding and cleaning up listeners in effects' , async ( ) => {
417
+ const root = ReactDOMClient . createRoot ( container ) ;
418
+
419
+ let logs = [ ] ;
420
+ function logClick ( e ) {
421
+ logs . push ( e . currentTarget . id ) ;
422
+ }
423
+
424
+ let rerender ;
425
+ let removeEventListeners ;
426
+
427
+ function Test ( ) {
428
+ const fragmentRef = React . useRef ( null ) ;
429
+ const [ _ , setState ] = React . useState ( 0 ) ;
430
+ rerender = ( ) => {
431
+ setState ( p => p + 1 ) ;
432
+ } ;
433
+ removeEventListeners = ( ) => {
434
+ fragmentRef . current . removeEventListener ( 'click' , logClick ) ;
435
+ } ;
436
+ React . useEffect ( ( ) => {
437
+ fragmentRef . current . addEventListener ( 'click' , logClick ) ;
438
+
439
+ return removeEventListeners ;
440
+ } ) ;
441
+
442
+ return (
443
+ < Fragment ref = { fragmentRef } >
444
+ < div id = "child-a" />
445
+ </ Fragment >
446
+ ) ;
447
+ }
448
+
449
+ // The event listener was applied
450
+ await act ( ( ) => root . render ( < Test /> ) ) ;
451
+ expect ( logs ) . toEqual ( [ ] ) ;
452
+ document . querySelector ( '#child-a' ) . click ( ) ;
453
+ expect ( logs ) . toEqual ( [ 'child-a' ] ) ;
454
+
455
+ // The event listener can be removed and re-added
456
+ logs = [ ] ;
457
+ await act ( rerender ) ;
458
+ document . querySelector ( '#child-a' ) . click ( ) ;
459
+ expect ( logs ) . toEqual ( [ 'child-a' ] ) ;
460
+
461
+ // The event listener
462
+ // Split into two tests
463
+ // 1. Removed event listeners are not added to new children
464
+ // 2. It can remove and reapply event listeners in effects
465
+ } ) ;
466
+
467
+ it ( 'does not apply removed event listeners to new children' , async ( ) => {
468
+ const root = ReactDOMClient . createRoot ( container ) ;
469
+ const fragmentRef = React . createRef ( null ) ;
470
+ function Test ( ) {
471
+ return (
472
+ < Fragment ref = { fragmentRef } >
473
+ < div id = "child-a" />
474
+ </ Fragment >
475
+ ) ;
476
+ }
477
+
478
+ let logs = [ ] ;
479
+ function logClick ( e ) {
480
+ logs . push ( e . currentTarget . id ) ;
481
+ }
482
+ await act ( ( ) => {
483
+ root . render ( < Test /> ) ;
484
+ } ) ;
485
+ fragmentRef . current . addEventListener ( 'click' , logClick ) ;
486
+ const childA = document . querySelector ( '#child-a' ) ;
487
+ childA . click ( ) ;
488
+ expect ( logs ) . toEqual ( [ 'child-a' ] ) ;
489
+
490
+ logs = [ ] ;
491
+ fragmentRef . current . removeEventListener ( 'click' , logClick ) ;
492
+ childA . click ( ) ;
493
+ expect ( logs ) . toEqual ( [ ] ) ;
494
+ } ) ;
495
+
415
496
describe ( 'with activity' , ( ) => {
416
497
// @gate enableFragmentRefs && enableActivity
417
498
it ( 'does not apply event listeners to hidden trees' , async ( ) => {
0 commit comments