oruga-ui / oruga

🐛 Oruga is a lightweight library of UI components without any CSS framework dependency
https://oruga-ui.com
MIT License
1.12k stars 169 forks source link

Hydration mismatch in Nuxt app after updating Oruga from 0.7 to 0.8.x #860

Closed andrzejkupczyk closed 1 month ago

andrzejkupczyk commented 7 months ago

Overview of the problem

Oruga version: 0.8.6 Vuejs version: 3.4.21 OS/Browser: macOS/Chrome

Description

I'm encountering a hydration mismatch issue with the Autocomplete component while upgrading my Nuxt 3.11.1 app from Oruga version 0.7 to 0.8.6.

image

I have noticed similar problem reports in vue and nuxt before, but afaik, those problems have been fixed. This issue does not impact other components in Oruga, and it functions properly in Oruga 0.7 version. Hence, I wanted to report the issue here.

Expected behavior

The autocomplete component has the same id on both the server and client side.

Actual behavior

The Autocomplete component on the client side receives a different ID, causing a mismatch in the hydration attribute.

andrzejkupczyk commented 7 months ago

I'm not sure if this will be helpful, but I came across this information: https://www.radix-vue.com/utilities/config-provider.html#hydration-issue-vue-3-5 I am unfamiliar with this framework, but it appears that the problem is comparable (link to the PR).

mlmoravek commented 7 months ago

Ok, so I have just learnt a bit. With nuxt the script is executed twice, once on the server and once on the client. However, in our case the id is generated randomly. So there will be a different id generated on the server then on the client.

But we have to wait some more time. A vue native useId composable is confirmed for vue 3.5 which should solve this problem. https://github.com/vuejs/rfcs/discussions/557

andrzejkupczyk commented 7 months ago

The reason the radix-vue authors referred to their solution as a temporary workaround is now clear. Thanks a bunch!

andrzejkupczyk commented 3 months ago

Hi again, @mlmoravek!

Unfortunately, this issue persists and appears to have more significant implications than I initially thought.

Although useId composable has been introduced and is available in Nuxt since v3.10, it’s not possible to set an ID for the Dropdown component which is utilized by Autocomplete.

I’m unsure whether this is relevant (I had the very same error with Tooltip but without the hydration mismatch issue), but my suspicion is that because of this hydration mismatch, the entire navigation crashes as it seems the component cannot be unmounted:

runtime-dom.esm-bundler.js:19 Uncaught (in promise) 
TypeError: Cannot read properties of null (reading 'parentNode')
    at remove (runtime-dom.esm-bundler.js:19:26)
    at Object.remove (runtime-core.esm-bundler.js:3510:7)
    at unmount (runtime-core.esm-bundler.js:5506:20)
    at unmountComponent (runtime-core.esm-bundler.js:5601:7)
    at unmount (runtime-core.esm-bundler.js:5496:7)
    at unmountChildren (runtime-core.esm-bundler.js:5621:7)
    at unmount (runtime-core.esm-bundler.js:5520:9)
    at unmountComponent (runtime-core.esm-bundler.js:5601:7)
    at unmount (runtime-core.esm-bundler.js:5496:7)
    at unmountComponent (runtime-core.esm-bundler.js:5601:7)

As a workaround, I had to opt-out of SSR and render the Autocomplete component only on the client side, which is quite unfortunate. Would it be possible to find a similar solution to what the authors of the Radix Vue have proposed? It's just a temporary measure.

When I have more time, I’ll try to create a reproducible example if necessary. I’m also open to a debug session or something similar 👍🏻

Edit I’ve just learned that Vue.js core v3.5.0-alpha.3 has been released, which seems promising. However, I was wondering if it would be a lot of effort to find a solution before the stable version is released.

mlmoravek commented 3 months ago

Hey @andrzejkupczyk, for sure we can implement a workaround until vue 3.5.

An reproducible example would be nice to make the issue clearer. However, feel free to make a PR with the proposed changes. It can be a propotype PR with the main implementation change, I can make the other parts and clean it up :)

mlmoravek commented 2 months ago

@andrzejkupczyk Vue 3.5 is out now! I will try to add the new useId() composable soon.

andrzejkupczyk commented 2 months ago

That’s great, thank you! Unfortunately, I couldn’t find the time to create a reproduction or draft a solution 😿 I apologize for that.