New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[Vue warn]: Hydration node mismatch: #12266
Comments
Do you still get hydration warnings when you wrap the |
Yes, here is the full source code <template>
<div class="fixed top-0 left-0 w-full z-10 p-3 dark:text-white backdrop-filter backdrop-blur-sm flex flex-wrap">
<div class="w-1/3">
<!-- warning here! -->
<a @click="menu" class="dark:text-white inline-block mt-1"><i data-feather="menu"></i></a>
<!-- -->
</div>
<div class="w-1/3 text-center font-bold">
<img src="https://nuxtjs.org/design-kit/colored-logo.svg" class="inline h-7 mr-1 -mt-2">
<p class="inline text-2xl dark:(text-gray-200)">Nuxt<span class="text-green-400">3</span></p>
<span class="inline ml-2 px-2 py-0.5 rounded bg-dark-300 text-xl">UI</span>
</div>
<div class="w-1/3 text-right">
<a class="dark:text-white inline-block mt-1"><i data-feather="moon"></i></a>
</div>
</div>
</template>
<script setup>
const menu = () => {
console.log('menu')
}
</script> |
Quite obvious that you have some transformation going on, as |
In my case, i just included feather icon on export default defineNuxtConfig({
meta: {
script: [
{ src: 'https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js' },
{ src: 'feather.init.js' }
],
}
}) I tried using
|
If you want to use the whole feather-icons package, I think it's easiest to implement a component which renders the icon to SVG, like so: <script>
import feather from "feather-icons";
export default {
props: {
icon: String,
validator: function (value) {
return typeof feather.icons[value] !== "undefined";
},
},
render(h) {
let svg = "";
if (typeof feather.icons[this.icon] !== "undefined") {
svg = feather.icons[this.icon].toSvg();
}
return h("i", {
class: {
icon: true,
},
domProps: {
innerHTML: svg,
},
});
},
};
</script>
<style scoped>
i {
display: inline-block;
}
</style> which could be used as follows <template>
<div id="app">
<Feather-Icon icon="x" />
<Feather-Icon icon="y" />
<Feather-Icon icon="award" />
<Feather-Icon icon="briefcase" />
</div>
</template>
<script>
import FeatherIcon from "./components/FeatherIcon";
export default {
name: "App",
components: {
FeatherIcon,
},
};
</script>
<style>
.icon {
color: #364fc7;
}
</style>
see https://codesandbox.io/s/happy-kare-hoy65?file=/src/components/FeatherIcon.vue:0-536 There are also other packages like vue-feather, but IMHO those packages often provide features which are not always required in every project... |
tracking need for |
Trying to wrap my head around this..:
Which probably stems from a problem with my if/else, as the form referenced up top is the form shown if <template>
<div class="w-full min-h-screen bg-white dark:bg-black dark:text-white p-8">
<div v-if="isAuthenticated()">
<Logout />
<h1 class="text-7xl font-bold mb-8">Brief.</h1>
<Content />
</div>
<Auth v-else />
</div>
</template>
<script setup lang="ts">
const { $supabase } = useNuxtApp();
const loading = ref(false);
const { isAuthenticated } = await useAuth();
</script>
import type { Session } from "@supabase/supabase-js";
// const authenticated = ref<boolean>(false);
// session is null when not logged in
const userSession = ref<Session | null>(null);
const userCookieSet = ref<boolean | null>(null);
export default async () => {
const isAuthenticated = () => {
return userSession.value?.user && userCookieSet.value;
};
return {
userSession,
userCookieSet,
isAuthenticated,
};
}; whereby Environment
|
I had this problem with font-awesome icons. My workaround was this: <font-awesome-icon
v-if="!loading"
icon="fa-solid fa-phone"
/> <script lang="ts" setup>
const loading = ref(true);
const nuxtApp = useNuxtApp();
nuxtApp.hook("page:finish", () => {
loading.value = false;
});
</script> This waits for the page to finish, i.e. the content to be present client-side. |
I had the same issue. I tried wrapping the div with
|
I have a very similar issue and it makes sense to me:
and terribly clutters my console. How can I turn these warnings off? |
You should pay attention to the warnings and add some handling on the client side to avoid updating the variable until your app has mounted. You can use |
I try to do my best taking all warnings and errors serious. Not sure how I could avoid it in my example, though: the server does not know anything about the screen size of the client. So the pages are served with my variable being the default value |
I got this error by using conditional logic inside a named slot in a base container template, like this:
Note how I thought like others that it might have been the feather library (loading in a separate component) that was the issue. Negative, removing that library had no effect. The issue was having the v-if="loading" inside the named slot. Upon removing the conditional logic from the Base template and moving that up to the parent template, no hydration error. Note in the above, I'm receiving loading as a prop. I may have been wrong here in the first place regarding conditional rendering inside a slot but still thought this was worth sharing in case someone else encounters the same. No v-if / conditional rendering inside named slots (or at least not in this example). Edit: More testing, identified that I can add conditional logic on BaseLoadingFeather component that loads the feather library without use of onNuxtReady if the loading slot is wrapped in a ClientOnly component. Thought that I had tested that specific (seems no), passing without hydration issues like this inside a base component template. Sharing in case this helps someone.
Use case is like this:
|
I'm using |
This fixed the issue for me I am new to nuxt, can you confirm tht this works with SSR ! |
This is a fairly common hydration mistake. So, I'll try to explain briefly. Your code: <template>
<div class=".1">
<div v-if="isAuthenticated()">
<logout />
<h1 class=".2">.3</h1>
<Content />
</div>
<div class="auth" v-else>.4</div>
</div>
</template>
<script setup lang="ts">
const { $supabase } = useNuxtApp();
const loading = ref(false);
const { isAuthenticated } = await useAuth();
</script> When <div class=".1">
<div class="auth">.4</div>
</div> Because Next, But the trick is that the When hydrated, The pickup goes like this: The Also, the setup code is executed BEFORE hydration or rendering. That is, the authorized client receives true in So if the client is authorized, when <div class=".1">
<div>
<logout />
<h1 class=".2">.3</h1>
<Content />
</div>
</div> With the actual (which came from the server): <div class=".1">
<div class="auth">.4</div>
</div> Which will cause a sync error. As a quick fix, consider using As the right solution, it is worth considering the migration of authorization to the client in full: <template>
<div class=".1">
<div v-if="isAuthenticated">
<logout />
<h1 class=".2">.3</h1>
<Content />
</div>
<div class="auth" v-else>.4</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
const { $supabase } = useNuxtApp();
const loading = ref(false);
const { isAuthenticated: checkIsAuthenticated } = await useAuth();
const isAuthenticated = ref(false);
onMounted(() => {
isAuthenticated.value = checkIsAuthenticated();
});
</script> The Even better, wrap your component in a custom Hope it's a little clearer.) |
This works for FontAwesome Items in Nuxt 3 , Thanks for sharing |
Will there still be SEO effects if clientOnly is used? |
If you are using |
In general, the question is rather complex. On the one hand, if you answer the question "will there be a disaster for SEO if I use Client Side Rendering?", then I think that most likely not. On the other hand, SSR greatly affects SEO metrics. So the answer is something like this: SSR is very likely to improve SEO performance, but even without SSR, you will not have a disaster. |
This comment was marked as resolved.
This comment was marked as resolved.
Let's simplify the context to focus on the problem.
<template>
<NuxtPage />
</template>
<template>
<div>
<p>Data...</p>
<div v-if="loading">loading</div>
<div v-else>not loading</div>
</div>
</template>
<script lang="ts" setup>
// Some random value, like loading, etc
const someComputedValue = ref(Math.random() > 0.5);
const loading = computed(() => someComputedValue.value);
</script> When reloading the page, sometimes (with a ~50% chance) a hydration error will occur. You need to synchronize the So, there are three ways to implement this synchronization, depending on your context:
ClientOnlyDisable SSR altogether for the problem area.
<template>
<div>
<p>Data...</p>
<ClientOnly>
<div v-if="loading">loading</div>
<div v-else>not loading</div>
<template #fallback>
<Loading />
</template>
</ClientOnly>
</div>
</template>
<script lang="ts" setup>
// Some random value, like loading, etc
const someComputedValue = ref(Math.random() > 0.5);
const loading = computed(() => someComputedValue.value);
</script> onMounted
<template>
<div>
<p>Data...</p>
<div v-if="loading">loading</div>
<div v-else>not loading</div>
</div>
</template>
<script lang="ts" setup>
// Some random value, like loading, etc
const someComputedValue = ref(Math.random() > 0.5);
const clientEnv = ref(false);
onMounted(() => (clientEnv.value = true));
const loading = computed(() => {
if (!clientEnv.value) {
return true;
}
return someComputedValue.value;
});
</script> You might figure out that the code is executed differently on the client, but in general the method looks like this. load only on clientIn this case, you ensure that
<template>
<NuxtPage />
</template>
<script setup>
import useNotificationStore from '~/stores/notification';
const notificationStore = useNotificationStore();
onMounted(() => notificationStore.loadNotifications());
</script> Now throughout the entire project you won't have hydration problems due to References: Which to choose? Without knowing your context, I suspect that In this case, the option with If you need SEO to display notifications, then I recommend the |
import * as flowbite from 'flowbite'; export default defineNuxtPlugin((nuxtApp) => { Working perfectly |
Environment
Linux
v14.18.1
3.0.0-27243104.5e903ae
Yarn
Vite
meta
,buildModules
-
nuxt-windicss@2.0.2
Describe the bug
A warning occurs in console when i add a
@click
attribute in html tagReproduction
.
Additional context
Logs
No response
The text was updated successfully, but these errors were encountered: