svelte icon indicating copy to clipboard operation
svelte copied to clipboard

SSR hydration bug with @html and localStorage

Open formula349 opened this issue 1 year ago • 6 comments

Describe the bug

I have a custom Table.svelte component that renders a table given an array of column definitions and an array of row data objects. This Table component supports sorting by clicking on the headers of the column and it saves that sort preference in localStorage.

When this component hydrates on the client you will see the table update to sort properly based on the last saved settings in localStorage. This is expected and works fine unless:

If any of the cells render using {@html cellValue}, the client-side sort will not update that column on initial render. This will leave some columns sorted properly and others not sorted and now associated with the wrong row.

It took a while to isolate this to the @html tag. I've tried all of the tricks for reactivity like [...data] array copying, {#key} and indexes on {#each} blocks. The only thing that fixed the sorting problem is to not use @html.

I'm working around this now by exposing a slot in my table component where I don't need to use @html, but this is definitely a problem for situations that require rendering HTML from a string.

Reproduction

https://www.sveltelab.dev/oksrlmbygtswbzd

  1. Load the sveltelab project and click on the Name column to sort by name. You should see the sorting working properly. image

  2. Click the UI view refresh to SSR and hydrate the page and you'll see the name sort kick in, but the names don't match the emails anymore. image

Logs

No response

System Info

New sveltelab.dev running on Chrome browser.

  System:
    OS: Linux 5.0 undefined
    CPU: (8) x64 Intel(R) Core(TM) i9-9880H CPU @ 2.30GHz
    Memory: 0 Bytes / 0 Bytes
    Shell: 1.0 - /bin/jsh
  Binaries:
    Node: 16.20.0 - /usr/local/bin/node
    Yarn: 1.22.19 - /usr/local/bin/yarn
    npm: 9.4.2 - /usr/local/bin/npm
    pnpm: 8.6.3 - /usr/local/bin/pnpm
  npmPackages:
    @sveltejs/adapter-auto: ^2.0.0 => 2.1.0 
    @sveltejs/kit: ^1.20.4 => 1.22.3 
    svelte: ^4.0.0 => 4.1.1 
    vite: ^4.3.6 => 4.4.7

Severity

serious, but I can work around it

Additional Information

This was confirmed by a few other users on the Svelte discord. See this thread for reference.

https://discord.com/channels/457912077277855764/1134549192174489630

formula349 avatar Jul 29 '23 03:07 formula349

I try with "{#each displayData as row, i (i)}" instead {#key sortIndex} and its works, can you try?

StagnantIce avatar Jul 29 '23 13:07 StagnantIce

That did not fix the problem. When you update the code it will sort it properly, so you'd have to refresh the app to see this SSR hydration bug again.

formula349 avatar Aug 01 '23 00:08 formula349

Same here. I've a wordy workaround using an "action" instead of @html as described here: https://youtu.be/R_C8jLh5yIs?t=13

Crenshinibon avatar Aug 16 '23 11:08 Crenshinibon

Will this be resolved any time soon or with Svelte 5 automatically?

I planned to go live this year and I'm relying on the @html heavily to translate many parts of my app.

Crenshinibon avatar Nov 07 '23 13:11 Crenshinibon

Take a look on the duplicated issue, the replication case is extremely easy to reproduce.

epavanello avatar Nov 16 '23 16:11 epavanello

This issue also appears in Svelte 5. A minimal repro is:

<div>{typeof window !== 'undefined'}</div>
<div>{@html typeof window !== 'undefined'}</div>

On page load, both divs will initially be false (expected). The first div will immediately change to true after hydration (expected). The second div will remain false (unexpected).

robertadamsonsmith avatar Apr 23 '24 11:04 robertadamsonsmith