Help Solving Hydration Error
Answered
shadow posted this in #help-forum
shadowOP
hey devs i have a hydration error and the solution seems to be simple but i can't manage to solve it.
i have a toploader that changes its color based on the current theme (light, dark)
TopLoader.tsx
and then im calling that component on the layout, but the color in the top loader is different in the server and the client
what can i do solve this difference between the client and server?
and its funny that the hydration error only trigger when im in light mode and the top loader gets triggered when changing pages
i have a toploader that changes its color based on the current theme (light, dark)
TopLoader.tsx
'use client'
import { useTheme } from 'next-themes'
import NextTopLoader from 'nextjs-toploader'
import React from 'react'
export default function TopLoader() {
const { theme, resolvedTheme } = useTheme()
const themeTopLoader = resolvedTheme === "light" ? "black" : "white";
return (
<div>
<NextTopLoader
showSpinner={true}
color={themeTopLoader}
/>
</div>
)
}and then im calling that component on the layout, but the color in the top loader is different in the server and the client
Error: Text content does not match server-rendered HTML.
See more info here: https://nextjs.org/docs/messages/react-hydration-error
<TopLoader>
<div>
<NextTopLoader>
<style>
"#nprogress{pointer-events:none}#nprogress .bar{background:white;position:fixed;z-index:1600;top: 0;left:0;width:100%;height:3px}..."
"#nprogress{pointer-events:none}#nprogress .bar{background:black;position:fixed;z-index:1600;top: 0;left:0;width:100%;height:3px}..."what can i do solve this difference between the client and server?
and its funny that the hydration error only trigger when im in light mode and the top loader gets triggered when changing pages
45 Replies
American Crow
Show
<NextTopLoader> codeshadowOP
its a library
https://www.npmjs.com/package/nextjs-toploader
https://www.npmjs.com/package/nextjs-toploader
American Crow
Oh shit and it does not expose something like className or styles at least i can't see it scrolling through.
My plan was to use
My plan was to use
dark: for the conditional styling that solved a similar issue i had once. But i think you cant control it that way@American Crow Oh shit and it does not expose something like className or styles at least i can't see it scrolling through.
My plan was to use `dark:` for the conditional styling that solved a similar issue i had once. But i think you cant control it that way
shadowOP
yea it doesnt expose className, i mean it works but the hydration error appear
@American Crow Oh shit and it does not expose something like className or styles at least i can't see it scrolling through.
My plan was to use `dark:` for the conditional styling that solved a similar issue i had once. But i think you cant control it that way
shadowOP
what u mean by that? on themetoploader variable?
they have this but i dont think that could work
template: to include custom HTML attributes for the TopLoader.American Crow
In a project with next-theme and tailwind i had a similar issue.
this resulted in a hydration Error
but this worked for me:
So i chose the 2nd way in my case
this resulted in a hydration Error
const themeTopLoader = resolvedTheme === "light" ? "black" : "white";but this worked for me:
<Mycomponent className="dark:text-white text-black" />So i chose the 2nd way in my case
@American Crow In a project with next-theme and tailwind i had a similar issue.
this resulted in a hydration Error
`const themeTopLoader = resolvedTheme === "light" ? "black" : "white";`
but this worked for me:
tsx
<Mycomponent className="dark:text-white text-black" />
So i chose the 2nd way in my case
shadowOP
something like that?
'use client'
import { useTheme } from 'next-themes'
import NextTopLoader from 'nextjs-toploader'
import React from 'react'
export default function TopLoader({ className }: { className?: string }) {
const { theme, resolvedTheme } = useTheme()
const themeTopLoader = resolvedTheme === "light" ? "black" : "white";
return (
<div className={className}>
<NextTopLoader
showSpinner={true}
color={themeTopLoader}
/>
</div>
)
}and maybe remove the color variable in the component
i think
American Crow
if the NextTopLoader inherits it maybe
i dont know how it works internally since its 3rd party
@shadow can you try one thing, import it without ssr
one sec imma send docs for that
@American Crow if the NextTopLoader inherits it maybe
shadowOP
NextTopLoader doesnt inherits the classes, it just uses the default one
Answer
import your loader component inside your layout, with that
American Crow
I mean you could do what @Arinji said but before that i'd simply
suppressHydrationWarning since there is not really a reason to load on on client only@shadow it worked
nice to know, can you do another thing for me?
make a useEffect, and listen for resolvedTheme, and do your check in there, and instead of assigning a variable, assign it to a state
makes sense?
also remove the no ssr thing
American Crow
can you try loading the whole component conditionally?
'use client'
import { useTheme } from 'next-themes'
import NextTopLoader from 'nextjs-toploader'
import React from 'react'
export default function TopLoader() {
const { theme, resolvedTheme } = useTheme()
//const themeTopLoader = resolvedTheme === "light" ? "black" : "white";
if (resolvedTheme === "light) {
return (
<div>
<NextTopLoader
showSpinner={true}
color="black"
/>
</div>
)
}
return (
<div>
<NextTopLoader
showSpinner={true}
color="white"
/>
</div>
)
}@Arinji makes sense?
shadowOP
if this is the right implementation, the error is appering:
'use client'
import { useTheme } from 'next-themes'
import NextTopLoader from 'nextjs-toploader'
import React, { useEffect, useState } from 'react'
export default function TopLoader() {
const { resolvedTheme } = useTheme()
const [theme, setTheme] = useState(resolvedTheme)
useEffect(() => {
const themeTopLoader = resolvedTheme === "light" ? "black" : "white";
setTheme(themeTopLoader)
} , [resolvedTheme])
return (
<div>
<NextTopLoader
showSpinner={true}
color={theme}
/>
</div>
)
}@American Crow can you try loading the whole component conditionally?
tsx
'use client'
import { useTheme } from 'next-themes'
import NextTopLoader from 'nextjs-toploader'
import React from 'react'
export default function TopLoader() {
const { theme, resolvedTheme } = useTheme()
//const themeTopLoader = resolvedTheme === "light" ? "black" : "white";
if (resolvedTheme === "light) {
return (
<div>
<NextTopLoader
showSpinner={true}
color="black"
/>
</div>
)
}
return (
<div>
<NextTopLoader
showSpinner={true}
color="white"
/>
</div>
)
}
shadowOP
and this is giving the error too
hmm, this feels like a next-themes issue in that case, can you try and remove the useTheme component?
i just want to see whats causing the issue
@Arinji hmm, this feels like a next-themes issue in that case, can you try and remove the useTheme component?
shadowOP
i used this approuch to test that:
and the color is correct
'use client'
import { useTheme } from 'next-themes'
import NextTopLoader from 'nextjs-toploader'
import React, { useEffect, useState } from 'react'
export default function TopLoader() {
// const { resolvedTheme } = useTheme()
const resolvedTheme = "dark"
const [theme, setTheme] = useState(resolvedTheme)
useEffect(() => {
const themeTopLoader = resolvedTheme === "light" ? "black" : "white";
setTheme(themeTopLoader)
} , [resolvedTheme])
return (
<div>
<NextTopLoader
showSpinner={true}
color={theme}
/>
</div>
)
}and the color is correct
shadowOP
yep
thank you for the help
awesome, mark an answer :D
@shadow thank you for the help
no problems
Original message was deleted
this is how you mark btw
shadowOP
@American Crow thank you for time spent here too :)
@shadow thank you for the help
btw thanks for helping me reach 100 answers :D
shadowOP
u deserve :p
@Arinji btw thanks for helping me reach 100 answers :D
Japanese Bobtail
congrats 😄