solid icon indicating copy to clipboard operation
solid copied to clipboard

Hard to move elements around using solid-js, insertExpression isn't fully DOM aware

Open danieltroger opened this issue 1 year ago • 3 comments

Describe the bug

When wanting to only create two components once, but then switching them around in the DOM (wrapping and unwrapping them), solid-js doesn't really play nicely.

According to a discord conversation this isn't intended behavior, so here's a bug report.

Why do I want to do this? For switching between desktop and mobile layouts I don't see a reason to rerender big components and all their children just to wrap/unwrap them in a div.

Your Example Website or App

https://playground.solidjs.com/anonymous/30690d0e-bff5-4cd5-9309-a847e3b08683

Steps to Reproduce the Bug or Issue

Version 1: Definitely a bug (crashes)

If you don't deem this misusing solid it's probably a bug:

  1. Go to https://playground.solidjs.com/anonymous/4d71a9de-a5b7-463b-8718-53e87d9ef5df
  2. Hit the button
  3. Uncaught DOMException: Failed to execute 'replaceChild' on 'Node': The new child element contains the parent.

From the error message, I suspect this could be avoided by using element.replaceWith or another one of the new DOM manipulation functions but I'm not sure (and I understand they are probably slower)

Version 2: Doesn't work as expected

This could be interpreted as expected behavior because there's no error but I'd still really love if this worked:

  1. Go to https://playground.solidjs.com/anonymous/1fe54bd3-2819-4a79-8bd9-bdaa7304d143
  2. Hit the button
  3. Elements disappear

Expected behavior

In example 1: No crash, element is moved

In example 2: Elements don't disappear, are moved instead

Screenshots or Videos

No response

Platform

  • OS: macOS 14.2.1 (23C71)
  • Browser: Chrome 120.0.6099.199 (Official Build) (arm64) , firefox 122.0b8

Additional context

No response

danieltroger avatar Jan 12 '24 19:01 danieltroger

I see. These are scenarios where you are keeping a DOM reference, and Solid thinks it knows where it was inserted, but when we get Solid to insert somewhere it is no longer where Solid thinks. This is the kind of issue I'd like to fix if it isn't prohibitive. The challenge is I imagine stuff not being where we expect could have a multitude of possible issues, but trying to fix these should have no impact on people not using these patterns accept if there is some some small performance considerations.

ryansolid avatar Jan 12 '24 19:01 ryansolid

In version 2 the bug is here: https://github.com/ryansolid/dom-expressions/blob/f691a482cea35336e7206759f0e8d2322f9371dd/packages/dom-expressions/src/reconcile.js#L72

What happens is that here

Screenshot 2024-01-15 at 11 02 33

The insert call that was done here is wrongly undone Screenshot 2024-01-15 at 11 03 57

(The two elements in a are now children of the two elements in b respectively)

danieltroger avatar Jan 15 '24 10:01 danieltroger

related:

  • https://playground.solidjs.com/anonymous/1cc13580-7844-439e-ba93-fcab4e030910
  • https://discord.com/channels/722131463138705510/1217034387938607145

titoBouzout avatar Mar 12 '24 22:03 titoBouzout