@@ -18,6 +18,7 @@ import {DataTransfer, DataTransferItem, DragEvent, FileSystemDirectoryEntry, Fil
1818import { Draggable , Droppable } from './examples' ;
1919import { DragTypes } from '../../src/dnd/utils' ;
2020import React , { useEffect } from 'react' ;
21+ import ReactDOM from 'react-dom' ;
2122import userEvent from '@testing-library/user-event' ;
2223
2324function pointerEvent ( type , opts ) {
@@ -397,6 +398,53 @@ describe('useDrag and useDrop', function () {
397398 expect ( onDropExit ) . toHaveBeenCalledTimes ( 1 ) ;
398399 } ) ;
399400
401+ it ( 'does not fire onDropEnter and onDropExit repeatedly for portal children' , ( ) => {
402+ let onDropEnter = jest . fn ( ) ;
403+ let onDropExit = jest . fn ( ) ;
404+ let portalContainer = document . createElement ( 'div' ) ;
405+ document . body . appendChild ( portalContainer ) ;
406+
407+ try {
408+ let tree = render (
409+ < Droppable onDropEnter = { onDropEnter } onDropExit = { onDropExit } >
410+ < >
411+ < div > Drop here</ div >
412+ { ReactDOM . createPortal (
413+ < >
414+ < div > Portal child 1</ div >
415+ < div > Portal child 2</ div >
416+ </ > ,
417+ portalContainer
418+ ) }
419+ </ >
420+ </ Droppable >
421+ ) ;
422+
423+ let portalChild1 = tree . getByText ( 'Portal child 1' ) ;
424+ let portalChild2 = tree . getByText ( 'Portal child 2' ) ;
425+
426+ let dataTransfer = new DataTransfer ( ) ;
427+ fireEvent ( portalChild1 , new DragEvent ( 'dragenter' , { dataTransfer, clientX : 1 , clientY : 1 } ) ) ;
428+ expect ( onDropEnter ) . toHaveBeenCalledTimes ( 1 ) ;
429+ expect ( onDropExit ) . not . toHaveBeenCalled ( ) ;
430+
431+ fireEvent ( portalChild2 , new DragEvent ( 'dragenter' , { dataTransfer, clientX : 1 , clientY : 1 , relatedTarget : portalChild1 } ) ) ;
432+ fireEvent ( portalChild1 , new DragEvent ( 'dragleave' , { dataTransfer, clientX : 1 , clientY : 1 , relatedTarget : portalChild2 } ) ) ;
433+ expect ( onDropEnter ) . toHaveBeenCalledTimes ( 1 ) ;
434+ expect ( onDropExit ) . not . toHaveBeenCalled ( ) ;
435+
436+ fireEvent ( portalChild1 , new DragEvent ( 'dragenter' , { dataTransfer, clientX : 1 , clientY : 1 , relatedTarget : portalChild2 } ) ) ;
437+ fireEvent ( portalChild2 , new DragEvent ( 'dragleave' , { dataTransfer, clientX : 1 , clientY : 1 , relatedTarget : portalChild1 } ) ) ;
438+ expect ( onDropEnter ) . toHaveBeenCalledTimes ( 1 ) ;
439+ expect ( onDropExit ) . not . toHaveBeenCalled ( ) ;
440+
441+ fireEvent ( portalChild1 , new DragEvent ( 'dragleave' , { dataTransfer, clientX : 1 , clientY : 1 } ) ) ;
442+ expect ( onDropExit ) . toHaveBeenCalledTimes ( 1 ) ;
443+ } finally {
444+ portalContainer . remove ( ) ;
445+ }
446+ } ) ;
447+
400448 describe ( 'nested drag targets' , ( ) => {
401449 let onDragStartParent = jest . fn ( ) ;
402450 let onDragMoveParent = jest . fn ( ) ;
0 commit comments