Skip to content

Commit 3bdf375

Browse files
authored
Merge pull request Expensify#65327 from callstack-internal/fix/63312-multi-files-follow-ups-part2
Change event target to counter to avoid extra rerenders
2 parents 445080e + 441d6c9 commit 3bdf375

1 file changed

Lines changed: 24 additions & 13 deletions

File tree

src/hooks/useDragAndDrop/index.ts

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,19 @@ const useDragAndDrop: UseDragAndDrop = ({
2626
const [isDraggingOver, setIsDraggingOver] = useState(false);
2727
const {close: closePopover} = useContext(PopoverContext);
2828

29-
const enterTarget = useRef<EventTarget | null>(null);
29+
const dragCounter = useRef(0);
30+
const debounceTimeoutRef = useRef<NodeJS.Timeout | null>(null);
3031

3132
useEffect(() => {
3233
if (isFocused && !isDisabled) {
3334
return;
3435
}
3536
setIsDraggingOver(false);
37+
dragCounter.current = 0;
38+
if (debounceTimeoutRef.current) {
39+
clearTimeout(debounceTimeoutRef.current);
40+
debounceTimeoutRef.current = null;
41+
}
3642
}, [isFocused, isDisabled]);
3743

3844
const handleDragEvent = useCallback(
@@ -73,30 +79,35 @@ const useDragAndDrop: UseDragAndDrop = ({
7379
event.stopPropagation();
7480
}
7581

82+
// Clear any existing debounce timeout
83+
if (debounceTimeoutRef.current) {
84+
clearTimeout(debounceTimeoutRef.current);
85+
debounceTimeoutRef.current = null;
86+
}
87+
7688
switch (event.type) {
7789
case DRAG_OVER_EVENT:
7890
handleDragEvent(event);
7991
break;
8092
case DRAG_ENTER_EVENT:
8193
handleDragEvent(event);
82-
enterTarget.current = event.target;
83-
if (isDraggingOver) {
84-
return;
94+
dragCounter.current += 1;
95+
if (dragCounter.current === 1 && !isDraggingOver) {
96+
setIsDraggingOver(true);
8597
}
86-
setIsDraggingOver(true);
8798
break;
8899
case DRAG_LEAVE_EVENT:
89-
if (!isDraggingOver) {
90-
return;
100+
dragCounter.current -= 1;
101+
if (dragCounter.current <= 0) {
102+
dragCounter.current = 0;
103+
// Add small debounce to prevent rapid flickering
104+
debounceTimeoutRef.current = setTimeout(() => {
105+
setIsDraggingOver(false);
106+
}, 50);
91107
}
92-
// This is necessary because dragging over children will cause dragleave to execute on the parent.
93-
if (enterTarget.current !== event.target) {
94-
return;
95-
}
96-
97-
setIsDraggingOver(false);
98108
break;
99109
case DROP_EVENT:
110+
dragCounter.current = 0;
100111
setIsDraggingOver(false);
101112
onDrop(event);
102113
break;

0 commit comments

Comments
 (0)