Skip to content

fix(dom): restore DOM elements on dragend to prevent removeChild crash#2102

Open
ElitoSear wants to merge 2 commits into
clauderic:mainfrom
ElitoSear:fix/dom-reconciliation-crash
Open

fix(dom): restore DOM elements on dragend to prevent removeChild crash#2102
ElitoSear wants to merge 2 commits into
clauderic:mainfrom
ElitoSear:fix/dom-reconciliation-crash

Conversation

@ElitoSear

Copy link
Copy Markdown

Summary

This PR fixes issues #1747 and #1780 where the application crashes with DOMException: Node.removeChild: The node to be removed is not a child of this node (or NotFoundError on Vite/Rollup) when dragging sortable items or elements across different groups/containers.

Cause of the Issue

During dragging operations, OptimisticSortingPlugin and Feedback directly manipulate the DOM tree (e.g., using insertAdjacentElement to reorder nodes, or appending dragging elements to a popover/overlay root element). When a drag operation ends, the framework (React/Solid/Vue/Svelte) updates state and reconciles the DOM tree. However, because the DOM structure was altered directly outside the framework, the virtual DOM reconciliation gets out of sync, leading to errors like parent.removeChild failing to find the target element.

Solution

  1. OptimisticSortingPlugin:
    • Capture the original parent and sibling elements of the dragging element on dragstart.
    • On dragend, always restore the dragging element back to its original parent and position synchronously before the framework reconciles the DOM.
  2. Feedback:
    • Detect if the feedback element is the real element itself (i.e. not using a separate DragOverlay).
    • If not using a separate DragOverlay, bypass the asynchronous drop animation and synchronously clean up / restore the element's original position on dragend to ensure a clean DOM state for the renderer's reconciliation tick.

This completely avoids any DOM reconciliation mismatches and resolves the crashes across all list component structures.

@changeset-bot

changeset-bot Bot commented Jul 4, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 17876fa

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 10 packages
Name Type
@dnd-kit/dom Patch
@dnd-kit/abstract Patch
@dnd-kit/collision Patch
@dnd-kit/geometry Patch
@dnd-kit/helpers Patch
@dnd-kit/react Patch
@dnd-kit/state Patch
@dnd-kit/vue Patch
@dnd-kit/solid Patch
@dnd-kit/svelte Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

…on-overlay elements

Guards against the drop-animation effect not firing in sync with the
dragend event, and makes cleanup idempotent since it can now be
triggered from two separate listeners.
@pkg-pr-new

pkg-pr-new Bot commented Jul 13, 2026

Copy link
Copy Markdown

Open in StackBlitz

@dnd-kit/abstract

npm i https://pkg.pr.new/@dnd-kit/abstract@2102

@dnd-kit/collision

npm i https://pkg.pr.new/@dnd-kit/collision@2102

@dnd-kit/dom

npm i https://pkg.pr.new/@dnd-kit/dom@2102

@dnd-kit/geometry

npm i https://pkg.pr.new/@dnd-kit/geometry@2102

@dnd-kit/helpers

npm i https://pkg.pr.new/@dnd-kit/helpers@2102

@dnd-kit/react

npm i https://pkg.pr.new/@dnd-kit/react@2102

@dnd-kit/solid

npm i https://pkg.pr.new/@dnd-kit/solid@2102

@dnd-kit/state

npm i https://pkg.pr.new/@dnd-kit/state@2102

@dnd-kit/svelte

npm i https://pkg.pr.new/@dnd-kit/svelte@2102

@dnd-kit/vue

npm i https://pkg.pr.new/@dnd-kit/vue@2102

commit: 17876fa

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant