Next.js Discord

Discord Forum

Help Solving Hydration Error

Answered
shadow posted this in #help-forum
Open in Discord
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
'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> code
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
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
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
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
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?
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>
    )
}
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?
i used this approuch to test that:

'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
ok so its not a thing on your side
package just goofy
import without ssr in this case
got it?
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
@American Crow thank you for time spent here too :)
@shadow thank you for the help
btw thanks for helping me reach 100 answers :D
u deserve :p
@Arinji btw thanks for helping me reach 100 answers :D
Japanese Bobtail
congrats 😄