svelte
svelte copied to clipboard
SSR hydration bug with @html and localStorage
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
-
Load the sveltelab project and click on the Name column to sort by name. You should see the sorting working properly.
-
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.
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
I try with "{#each displayData as row, i (i)}" instead {#key sortIndex} and its works, can you try?
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.
Same here. I've a wordy workaround using an "action" instead of @html as described here: https://youtu.be/R_C8jLh5yIs?t=13
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.
Take a look on the duplicated issue, the replication case is extremely easy to reproduce.
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).