Skip to content

Commit

Permalink
fix: "Invariant Violation: Expected targetIds to be registered."
Browse files Browse the repository at this point in the history
We've sporadically seen this error from customers. The call stack
indicates that it's originating from HTML5BackendImpl's
handleTopDragOver's requestAnimationFrame callback.  I've been unable to
reproduce it locally; however, if I simulate a slowdown by replacing
`requestAnimationFrame(callback)` with `setTimeout(callback, 10000)`, I
can fairly reliably reproduce this error.

To fix it, I believe HTML5BackendImpl should consistently clear the
hover animation whenever the drag operation is ended for any reason.

I locally tested this fix in the v15.1.2 tag, and it appeared to work.

Fixes #763, #3403
  • Loading branch information
joshkel committed Mar 22, 2022
1 parent 0830641 commit 99db7b8
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 15 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Contributing to React-DnD

So you want to contibute to React-DnD? Thank you! This library is a community effort, and your contributions are greatly appreciated.
So you want to contribute to React-DnD? Thank you! This library is a community effort, and your contributions are greatly appreciated.

## FAQ

Expand Down
47 changes: 33 additions & 14 deletions packages/backend-html5/src/HTML5BackendImpl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,6 +347,7 @@ export class HTML5BackendImpl implements Backend {
if (this.clearCurrentDragSourceNode() && this.monitor.isDragging()) {
this.actions.endDrag()
}
this.cancelHover()
}

private setCurrentDragSourceNode(node: Element | null) {
Expand Down Expand Up @@ -400,6 +401,33 @@ export class HTML5BackendImpl implements Backend {
return false
}

private scheduleHover = (dragOverTargetIds: string[] | null) => {
if (
this.hoverRafId === null &&
typeof requestAnimationFrame !== 'undefined'
) {
this.hoverRafId = requestAnimationFrame(() => {
if (this.monitor.isDragging()) {
this.actions.hover(dragOverTargetIds || [], {
clientOffset: this.lastClientOffset,
})
}

this.hoverRafId = null
})
}
}

private cancelHover = () => {
if (
this.hoverRafId !== null &&
typeof cancelAnimationFrame !== 'undefined'
) {
cancelAnimationFrame(this.hoverRafId)
this.hoverRafId = null
}
}

public handleTopDragStartCapture = (): void => {
this.clearCurrentDragSourceNode()
this.dragStartSourceIds = []
Expand Down Expand Up @@ -429,6 +457,7 @@ export class HTML5BackendImpl implements Backend {
// Avoid crashing if we missed a drop event or our previous drag died
if (this.monitor.isDragging()) {
this.actions.endDrag()
this.cancelHover()
}

// Don't publish the source just yet (see why below)
Expand Down Expand Up @@ -530,6 +559,7 @@ export class HTML5BackendImpl implements Backend {
// Only proceed if we have not handled it already.
this.actions.endDrag()
}
this.cancelHover()
}

public handleTopDragEnterCapture = (e: DragEvent): void => {
Expand Down Expand Up @@ -622,20 +652,7 @@ export class HTML5BackendImpl implements Backend {
this.altKeyPressed = e.altKey
this.lastClientOffset = getEventClientOffset(e)

if (
this.hoverRafId === null &&
typeof requestAnimationFrame !== 'undefined'
) {
this.hoverRafId = requestAnimationFrame(() => {
if (this.monitor.isDragging()) {
this.actions.hover(dragOverTargetIds || [], {
clientOffset: this.lastClientOffset,
})
}

this.hoverRafId = null
})
}
this.scheduleHover(dragOverTargetIds)

const canDrop = (dragOverTargetIds || []).some((targetId) =>
this.monitor.canDropOnTarget(targetId),
Expand Down Expand Up @@ -672,6 +689,7 @@ export class HTML5BackendImpl implements Backend {
if (this.isDraggingNativeItem()) {
setTimeout(() => this.endDragNativeItem(), 0)
}
this.cancelHover()
}

public handleTopDropCapture = (e: DragEvent): void => {
Expand Down Expand Up @@ -709,6 +727,7 @@ export class HTML5BackendImpl implements Backend {
} else if (this.monitor.isDragging()) {
this.actions.endDrag()
}
this.cancelHover()
}

public handleSelectStart = (e: DragEvent): void => {
Expand Down

0 comments on commit 99db7b8

Please sign in to comment.