Closed gkkirilov closed 7 months ago
This module uses ^1.0.0 syntax for the headless UI version, so that you can install whatever version you like and can update headless UI without updating this dependency. Just refresh your lock file, or install the latest version manually.
Remember that the fix requires you to add code to your app.vue file to provide the id generation function. This module can't do this for you due to limitations with the useId hook by nuxt. Headless UI 2 will add this feature by default using Vue 3.5 builtin useId function.
@P4sca1
I just made a reproduction because I still had mismatches after using the recommended fix. Turns out it only happens if I am using the Components through your module. Importing the components explicitly fixes the mismatches. You can easily check by un-commenting the imports.
i can confirm this issue!
I can reproduce the issue, but did not yet find the reason for it. My guess right now is a symbol mismatch due to different imports, but I am not sure yet. I will provide an update once I know more.
I invested a few hours today, but was unable to find out why this is not working.
For some reason the provided useId
function is called on the server, but not on the client. So on the client the IDs are still generated using -i
suffixes, leading to hydration mismatches.
I also tried calling provideUseId
in a plugin added by this module without success.
@P4sca1 yeah i also could the in the DOM that the ids with the -i suffixe where generated
adding this to app.vue fixed it for me, at least until we get a proper fix
import { provideUseId } from '@headlessui/vue'
provideUseId(() => useId())
Looking at the network logs, it looks like my import
statement within app.vue is fetching Headless UI from _nuxt/node_modules/.cache/vite/client/deps/@headlessui_vue.js
—which is fully bundled—but the component from /_nuxt/node_modules/@headlessui/vue/dist/components/menu/menu.js
. Therefore, there are two separate, incompatible copies of the library included. I also noticed a Vite log that it was "optimizing dependencies" when I added that line to app.vue for the first time.
To fix it, exclude the library from being optimized by Vite:
vite: {
optimizeDeps: {
exclude: ['@headlessui/vue'],
},
},
It is my understanding that dependencies are not pre-bundled during production at all (i.e. this is a dev only problem), so this should have no performance or size impact on the final build.
Interesting find. Because there are 2 different bundles, the symbols that get injected likely don't match, which is causing the issue. Thank you for posting a workaround. I will check if it makes sense to include it by default.
This issue is likely related https://github.com/vitejs/vite/issues/3910 and mentions the same workaround.
nuxt-headssui
version 1.2.0 exposes a new provideHeadlessUseId
composable, which should fix the issue.
Add the following to your app.vue
file in <script setup>
(everything is auto-imported):
// Use SSR-safe IDs for Headless UI
provideHeadlessUseId(() => useId())
nuxt-headssui
version 1.2.0 exposes a newprovideHeadlessUseId
composable, which should fix the issue. Add the following to yourapp.vue
file in<script setup>
(everything is auto-imported):// Use SSR-safe IDs for Headless UI provideHeadlessUseId(() => useId())
is this auto import ?
@geofany Ensure you are using Nuxt 2.10 or newer. If you have auto imports disabled, import the composables manually.
can this be useful now: https://blog.vuejs.org/posts/vue-3-5#useid
can this be useful now: https://blog.vuejs.org/posts/vue-3-5#useid
Yes, but it needs to be integrated into @headlessui/vue
directly.
If you upgrade vue to 3.5.0 or newer and @headlessui/vue
to 1.7.23 or newer, nuxt-headlessui
will automatically use the native useId
function provided by vue. There is no need to update nuxt-headlessui
. You can remove provideHeadlessUseId()
from your app.vue
function. If you keep it, it will just do nothing.
HeadlessUI deployed a fix for Nuxt hydration error for generated ids.
Reference: https://github.com/tailwindlabs/headlessui/issues/2913