Skip to content

Spread on element with innerHTML clears content during reactive updates after SSR hydration #2737

@youyoumu

Description

@youyoumu

Describe the bug

When using the spread operator on an element that also has innerHTML defined a reactive update to the spread
object causes the element's content to be cleared if the app was hydrated from SSR. This does not happen when SSR is disabled or
when attributes are bound individually.

function App() {
  const [count, setCount] = createSignal(0);
  const [ref, setRef] = createSignal<HTMLDivElement>();

  // Reactive object for spread
  const data = createMemo(() => {
    return {
      "data-whatever": count() === 1 ? "yes" : "no",
    };
  });

  onMount(() => {
    console.log(ref()?.textContent); // Hello world! (Correct)
    setCount(1);
    setTimeout(() => {
      console.log(ref()?.textContent); // "" (BUG: Should be "Hello world!")
      console.log(ref()?.getAttribute("data-whatever")); // yes (Correct)
      console.log(ref()?.getAttribute("class")); // flex (correct)
      console.log(ref()?.getAttribute("style")); // color: red (Correct)
    }, 500);
  });

  return (
    <div
      ref={setRef}
      {...data()}
      class="flex"
      style="color: red"
      innerHTML="Hello world!"
    ></div>
  );
}

Your Example Website or App

https://stackblitz.com/github/youyoumu/solid-spread-hydration-bug

Steps to Reproduce the Bug or Issue

https://github.com/youyoumu/solid-spread-hydration-bug

  1. Clone the repo and install the dependency
  2. Run the dev server
  3. Open the dev server in browser and see the dom and the console.log ouput
  4. change ssr to false on app.config.ts to confirm the bug only happen with ssr

Expected behavior

The innerHTML should remain intact when the spread object is updated, as long as the spread object does not contain a children or innerHTML key.

Actual Behavior

The element's content is cleared immediately upon the first reactive update of the spread object after hydration.

Screenshots or Videos

Picture of chrome dev tools showing div with data-whatever="yes" having no children/innerHTML
Image

Picture of console output
Image

Platform

  • OS: Linux
  • Browser: Chrome
  • Version: 147.0.7727.116 (Official Build) (64-bit)

Additional context

  • The bug only occurs when ssr: true. With ssr: false, it works as expected.
  • If the attributes are bound individually (e.g., data-whatever={count() === 1 ? "yes" : "no"}) instead of using a spread, the bug does not occur.

Tested on

SolidJS + Vite

  "dependencies": {
    "@floating-ui/dom": "^1.7.6",
    "solid-js": "^1.9.13"
  },

SolidStart 1

  "dependencies": {
    "@solidjs/start": "1.3.2",
    "solid-js": "^1.9.5",
    "vinxi": "^0.5.7"
  },

SolidStart 2

  "dependencies": {
    "@solidjs/start": "2.0.0-alpha.2",
    "solid-js": "^1.9.5",
    "vite": "^7.0.0",
    "@solidjs/vite-plugin-nitro-2": "^0.1.0"
  },

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions