-
-
Notifications
You must be signed in to change notification settings - Fork 1k
Description
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