Problem when refreshing page
Unanswered
Little fire ant posted this in #help-forum
Little fire antOP
navbar.tsx * this is where i am experiencing the issue
const { setTheme, resolvedTheme } = useTheme()
layout.tsx
providers.tsx
theme-switch.tsx
const { setTheme, resolvedTheme } = useTheme()
<div className={cn("p-[0.4rem] mb-12 sticky z-[100] backdrop-blur-md border", resolvedTheme === "dark" ? "border-slate-800/90 bg-slate-900/90" : "border border-slate-800/10 bg-slate-900/10")}>
<nav className="sm:px-12 md:px-15 lg:px-20 flex gap-2 relative justify-start w-full z-[100] rounded-lg justify-around">
<div className="flex">
<SignedIn>
<div className="self-center mx-4">
<UserButton afterSignOutUrl="/" />
</div>
</SignedIn>
<SignedOut>
<Link href="/sign-in" className="self-center">
<div className="rounded-full bg-purple-500/30 p-2 border-1 border-purple-800">
<UserPlus2 size="14" className={cn("", resolvedTheme === "dark" ? "text-purple-300" : "text-purple-800")}/>
</div>
</Link>
</SignedOut>
</div>layout.tsx
import type { Metadata } from "next";
import { Inter } from "next/font/google";
import "./globals.css";
import { ClerkProvider } from "@clerk/nextjs";
import Navbar from "@/components/navbar";
import { Providers } from "./providers";
import { useTheme } from "next-themes";
const inter = Inter({ subsets: ["latin"] });
export const metadata: Metadata = {
title: "Sean Devereux",
description: "Generated by create next app",
};
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<ClerkProvider>
<html lang="en" suppressHydrationWarning>
<body>
<Providers>
<Navbar/>
{children}
</Providers>
</body>
</html>
</ClerkProvider>
);
}providers.tsx
"use client";
import { ThemeProvider } from "next-themes";
export function Providers({ children } : { children: React.ReactNode}) {
return <ThemeProvider attribute="class" defaultTheme="dark">{children}</ThemeProvider>
}theme-switch.tsx
"use client"
import * as React from "react"
import { Moon, Sun } from "lucide-react"
import { useTheme } from "next-themes"
import { Button } from "@/components/ui/button"
import { useEffect, useState } from "react"
export function ModeToggle() {
const { setTheme, resolvedTheme } = useTheme()
const [mounted, setMounted] = useState(false)
// useEffect only runs on the client, so now we can safely show the UI
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) {
return null
}
return (
<>
<Button variant="outline" className="rounded-full" size="icon" onClick={resolvedTheme === "dark" ?() => setTheme("light") : () => setTheme("dark")}>
<Sun className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
<Moon className="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
<span className="sr-only">Toggle theme</span>
</Button>
</>
)
}53 Replies
Little fire antOP
I have a condition for the current theme, however when i f5 the page the colors don't load correctly.
how it looks when i f5
and this is how its meant to look
and it looks like this after i press the dark mode button
twice, to go back to dark mode
Plott Hound
Are you using next-themes?
Little fire antOP
yea i am
Plott Hound
Whats in your browser local storage ? It should have a value for theme
Little fire antOP
i havent saved anything to local storage atm
i am quite new to nextjs btw
Plott Hound
next-themes stores the value of the current theme in local storage so you should be able to see if it’s working and what it’s doing
Also I would strongly advise against suppress hydration on your html or body tags
Little fire antOP
ah i think i read something about that on the next-themes documentation, i'll have a look
do i have to manually store it to local storage?
or is it automatic?
Plott Hound
It looks like you are on the right path with using the providers file to make the theme context work
@Little fire ant or is it automatic?
Plott Hound
Yes it’s automatic
It stores the user’s theme value in local storage so the browser remembers it
Sometimes it can get messed up so it’s a good place to check first
I’m a bit confused why you are importing use theme in your layout file. Since that’s a client function did you make your layout file use client?
Little fire antOP
do you know how i could look for the variable in local storage?
and yea i think i was just playing around tbh
Plott Hound
Open your browser inspector and go to the storage tab
Little fire antOP
and my layout file is not use client i think that threw an error when i tried
however when i debugged earlier, it seemed that it was set to empty
looks like a hydration error?
i added the code from the docs for the button to avoid the hydration error and it works now, however loading times are noticeably longer. the code i added to the navbar component was "
const [mounted, setMounted] = useState(false)
// useEffect only runs on the client, so now we can safely show the UI
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) {
return null
}"Plott Hound
next themes does tend to throw hydration errors. this is because the server cant know what the theme is set to since its stored on the client. so the client has to mount before being able to read the theme from localstorage then apply it as a class to your body
this is why we use useEffect for the toggle
@Little fire ant i added the code from the docs for the button to avoid the hydration error and it works now, however loading times are noticeably longer. the code i added to the navbar component was " const [mounted, setMounted] = useState(false)
// useEffect only runs on the client, so now we can safely show the UI
useEffect(() => {
setMounted(true)
}, [])
if (!mounted) {
return null
}"
Plott Hound
this should stop the hydration error by waiting for the client to mount before figuring out what the theme is
when you do a hard f5 refresh does your body have class="dark" ?
check it and see if it changes when you press the dark mode toggle
Little fire antOP
the body remains to have no class i think
if light or dark
ah i see sorry
the html tag updates accordingly
@Plott Hound this is why we use useEffect for the toggle
Little fire antOP
use effect for the toggle? in the theme-switch class?
Plott Hound
sorry i meant html not body
so it has class="dark" on html when you hard refresh?
Little fire antOP
yea, it seems to be working well now
thanks very much
i think from here i'll add a loader screen
and when everything has finished loading display it
Plott Hound
ayyy good job dude
no worries. if you could mark my answer as the solution it would be appreciated thanks
@Little fire ant and when everything has finished loading display it
Plott Hound
yeah this is what i do. i basically use a skeleton of my theme switcher until everything is loaded then display the actual switcher so there is no ui glitch while it waits to load