lustre-labs / lustre

A Gleam web framework for building HTML templates, single page applications, and real-time server components.
https://hexdocs.pm/lustre
MIT License
1.12k stars 72 forks source link

Wrapping server component view in `element.fragment` breaks DOM patching #193

Open JonasGruenwald opened 5 days ago

JonasGruenwald commented 5 days ago

Hiya! I think I found a small issue with server components, not sure if this is something that's known already.

Steps

fn view(model: Model) -> Element(Msg) {
  let styles = [#("width", "100vw"), #("height", "100vh"), #("padding", "1rem")]
  let count = int.to_string(model)
  element.fragment([
    ui.centre(
      [attribute.style(styles)],
      ui.stack([], [
        ui.button([event.on_click(Incr)], [element.text("+")]),
        html.slot([]),
        html.p([attribute.style([#("text-align", "center")])], [
          element.text(count),
        ]),
        ui.button([event.on_click(Decr)], [element.text("-")]),
      ]),
    ),
  ])
}

What happens

The server component is rendered but not interactive, when clicking the buttons the following error is logged to the browser console:

Uncaught TypeError: Cannot read properties of null (reading 'childNodes')
    at getDeepChild (lustre-server-component.mjs:318:19)
    at patch (lustre-server-component.mjs:57:18)
    at #diff (lustre-server-component.mjs:566:5)
    at LustreServerComponent.messageReceivedCallback (lustre-server-component.mjs:498:26)
    at WebSocket.<anonymous> (lustre-server-component.mjs:488:31)
getDeepChild @ lustre-server-component.mjs:318
patch @ lustre-server-component.mjs:57
#diff @ lustre-server-component.mjs:566
messageReceivedCallback @ lustre-server-component.mjs:498
(anonymous) @ lustre-server-component.mjs:488
hayleigh-dot-dev commented 5 days ago

Ah no, how frustrating! I think we've had problems with fragments and server components in the past. I'm in the middle of a move of country at the moment so my bandwidth to fix things is a bit limited, but I'll see if I can solve it soon!

JonasGruenwald commented 5 days ago

Ah yeah no rush with this at all! I ended up not needing the element.fragment anyways for what I'm working on but had left it my view in by accident and noticed things stopped working.