solid icon indicating copy to clipboard operation
solid copied to clipboard

Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node

Open kachurun opened this issue 5 months ago • 3 comments

Describe the bug

I'm creating a DND library on top of dnd-kit/dom and have run into this issue. By nature, sorting libraries use optimistic updates in the DOM tree to perform updates on the fly. Once complete, I need to sync the current DOM order with the order in my data. Sometimes this works well, but other times Solid tries to sort nodes that were already sorted by the optimistic DND update. In some cases, it even throws the error: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node.

Your Example Website or App

Unexpected move: https://playground.solidjs.com/anonymous/759847e3-477a-4a02-bd70-48d05d87a87e

Throw: https://playground.solidjs.com/anonymous/4d15e0bf-5bbb-4784-bc77-b96000ccd884

Steps to Reproduce the Bug or Issue

Render the list of 5 elements: createSignal([1, 2, 3, 4, 5]) Move element 1 after 4 in the DOM. Sync the order in the data: setItems([2, 3, 4, 1, 5]) → Solid will reorder the items, so instead of the expected 2 3 4 1 5, you'll get 3 4 1 2 5.


Render the list of 5 elements: createSignal([1, 2, 3, 4, 5]) Move element 3 after 5 in the DOM. Sync the order in the data: setItems([1, 2, 4, 5, 3]) → Solid will throw an error, and you'll get 1 2 5 4.

Expected behavior

I fully understand the nature of SolidJS and why this happens, but it would be good to have some way to force the correct order of items in For without completely rerendering the whole list. Or at least, not throw an error in the second case. I’ve tried using For/Index and Keyed from solid-primitives, but nothing helps. The only two ways I've found to solve this are: restoring the original order of DOM items before calling setItems, which is tricky and unreliable; or completely rerendering the whole list, which is slow and also breaks transitions for the DND library. I also tried to find a way to memoize DOM nodes after rendering to restore them when rerendering the list, but I didn’t succeed. Maybe someone knows a way to do this.

Screenshots or Videos

No response

Platform

  • OS: -
  • Browser: Any
  • Version: ^1.9

Additional context

No response

kachurun avatar Jul 14 '25 16:07 kachurun

Related but closed (not solved) issue https://github.com/solidjs/solid/issues/1898

kachurun avatar Jul 14 '25 16:07 kachurun

This is the issue https://github.com/ryansolid/dom-expressions/pull/388

Basically what's happening is that solid takes some shortcuts (for performance reasons [albeit this can be fixed without losing performance]).

To illustrate it, instead of taking the first node in the list, it does something on the lines of parent.firstChild, assuming the first child is still the first item in the list. So if you happen to move nodes around, then the assumption that the first node is the first item in the list is broken and well.

This code was written ages ago, while the linked issue seems a bit stalled its highly considered, and hopefully we can fix this.

titoBouzout avatar Jul 14 '25 22:07 titoBouzout

The thing is moving the items back to where they were is how all DnD has worked to my knowledge with declarative frameworks from the beginning of time. Or basically you don't actually drop the element, you just capture that it would be dropped and then update the data that would make it re-render properly. This is how it has worked in every framework forever. We get this issue from time to time and I generally point people to they are doing things wrong.

I am not convinced that the elements can be made out of order and we won't hit an issue sometime in the future because the framework assumes it knows where everything is. It seems like an invitation to endless edge cases. Obviously if someone was to solve this in a performant way it would be huge, but I'd be cautious getting ones hopes up.

ryansolid avatar Jul 16 '25 16:07 ryansolid