icon icon indicating copy to clipboard operation
icon copied to clipboard

Hydration mismatch with useId() if <Icon /> is used

Open robinscholz opened this issue 1 year ago • 1 comments

We’ve consistently ran into issues with hydration and useId across some Nuxt projects and I think we finally found the culprit. I've forked the example from https://github.com/nuxt/icon/issues/310 and slightly altered it to reproduce the issue. Both svg and css mode lead to the error. Might it be related to the custom api endpoint?

[Vue warn]: Hydration attribute mismatch on <input id=​"v-1-0">​ 
  - rendered on server: id="v-1-0"
  - expected on client: id="v-0-0"
  Note: this mismatch is check-only. The DOM will not be rectified in production due to performance overhead.
  You should fix the source of the mismatch. 
  at <CustomInput> 
  at <TestComponent> 
  at <App key=4 > 
  at <NuxtRoot>

The reproduction can be found here: https://stackblitz.com/edit/github-pz2kcg-jtmax8ot?file=nuxt.config.ts

robinscholz avatar Feb 13 '25 13:02 robinscholz

The useFetch call inside TestComponent.vue is needed to trigger the error as well.

robinscholz avatar Feb 17 '25 14:02 robinscholz

Same Issue after useFetch()

luca-smartpricing avatar Feb 26 '25 12:02 luca-smartpricing

Ugh :( Just spent all day trying to figure this out and finally came across this thread at the end.

I thought my input+hydration mismatch issues were caused by Vuetify. Their dev team recently put together some fixes to resolve hydration issues and moved from getUuid to Vue's setId. I updated my app to use their new 3.8 beta release only to find the hydration issue wasn't fixed for me and it looks like it was an issue with nuxt/icon from the start.

I see a @nuxt/icon fix was made for the icon module to resolve hydration mismatch issues, but it appears to only apply to CSS icons - I think something like it needs to be made for SVG?

My example below reproduces the problem when in SVG mode:

https://stackblitz.com/edit/vitejs-vite-a8edpmzn (first ever use of Stackblitz, hope it works!)

I made what appears to be a change for SVG mode that clears up the hydration input bug. I'm still getting some hydration issues, but I think they're related to a scheme I have that lets me use my nuxt-icon icons with Vuetify.

Stackblitz which uses a fork of nuxt-icon with the minor changes made to wrap the SVG icon server initialization in the onServerPrefetch function:

https://stackblitz.com/edit/vitejs-vite-oxw3dzpq

PR submitted here: https://github.com/nuxt/icon/pull/377

benlavalley avatar Mar 24 '25 06:03 benlavalley

@robinscholz I applied my @nuxt/icon fix to your own reproduction and it cleared up the hydration mismatch errors:

https://stackblitz.com/edit/github-pz2kcg-ekvc5nmu

If you want to load the fixes in another app, just point your @nuxt/icon to my icon fork in your package.json (e.g. "@nuxt/icon": "git://github.com/benlavalley/icon#cc0582c")

In addition to applying the CSS fix to wrap the server-side icon loading in onServerPrefetch, the SVG icon code also seemed to be missing 'await' before useAsyncData - I was getting continued hydration errors with classes not aligning and the viewBox properties not matching until I added this.

benlavalley avatar Mar 25 '25 22:03 benlavalley