Next.js Discord

Discord Forum

ThemeContext problem

Unanswered
Kryp Arnold posted this in #help-forum
Open in Discord
Hello guys, i have a simple ThemeContext like this;
"use client"
import { createContext, ReactNode, useContext, useEffect, useState } from "react";

export enum ThemeKeys {
    DARK = "dark",
    LIGHT = "light",
    SLATE = "slate",
    GRAY = "gray"
}

type Themes = {
    [x in ThemeKeys]: {
        textColor: string;
        bgColor: string;
    };
}

export const themes: Themes = {
    "dark": {
        textColor: "0 0% 100%",
        bgColor: "0 0% 0%"
    },
    "light": {
        textColor: "0 0% 0%",
        bgColor: "0 0% 100%"
    },
    "slate": {
        textColor: "220 13% 91%",
        bgColor: "215 16% 47%"
    },
    "gray": {
        textColor: "291 93% 83%",
        bgColor: "240 5% 26%"
    }
}

export type ThemeContextType = {
    currentTheme: ThemeKeys;
    setTheme: (themeKey: ThemeKeys) => void;
}

const ThemeContext = createContext<ThemeContextType | undefined>(undefined);

export const ThemeProvider = ({ children }: { children: ReactNode }) => {
    const [theme, setTheme] = useState<ThemeKeys>(ThemeKeys.DARK);

    useEffect(() => {
        const storedTheme = localStorage.getItem("theme") as ThemeKeys;

        if (storedTheme) {
            setTheme(storedTheme);
        }
    }, []);

    useEffect(() => {
        localStorage.setItem("theme", theme);

        const root = document.documentElement;

        root.style.setProperty("--primary-text", themes[theme].textColor);
        root.style.setProperty("--primary-bg", themes[theme].bgColor);
    }, [theme]);

    return (
        <ThemeContext.Provider value={{ currentTheme: theme, setTheme: (themeKey: ThemeKeys) => setTheme(themeKey) }}>
            {children}
        </ThemeContext.Provider>
    );
}

export function useTheme() {
    const context = useContext(ThemeContext);

    if (context === undefined) {
        throw new Error('useTheme must be used within a ThemeProvider');
    }

    return context;
}

2 Replies

the problem is that when i load my website first time, it flickers for a second, how can i read the localStorage before initiating ThemeContext?
American Crow
I'd suggest using https://github.com/pacocoursey/next-themes

Or have a look at how they do it in the provider