Skip to content

Commit 7d0ebce

Browse files
committed
fix: Theme initialization handling with useRef for DOM sync
1 parent e865d7e commit 7d0ebce

1 file changed

Lines changed: 10 additions & 7 deletions

File tree

src/context/ThemeContext.tsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"use client";
22

3-
import React, { createContext, useContext, useState, useEffect, useLayoutEffect } from "react";
3+
import React, { createContext, useContext, useState, useEffect, useLayoutEffect, useRef } from "react";
44

55
export type Theme = "dark" | "light";
66

@@ -15,19 +15,22 @@ const ThemeContext = createContext<ThemeContextValue>({
1515
});
1616

1717
export function ThemeProvider({ children }: { children: React.ReactNode }) {
18-
// Always start with "dark" on both server and client — matches the SSR default.
19-
// useLayoutEffect runs before paint and syncs with whatever the inline theme-init
20-
// script already applied to <html>, so there's no visible flash.
2118
const [theme, setTheme] = useState<Theme>("dark");
19+
// Track whether the initial DOM sync has completed — we must not write
20+
// localStorage until we've read the real theme from the DOM.
21+
const initialised = useRef(false);
2222

2323
useLayoutEffect(() => {
2424
const actual: Theme = document.documentElement.classList.contains("dark") ? "dark" : "light";
25-
// eslint-disable-next-line react-hooks/set-state-in-effect
26-
if (actual !== "dark") setTheme(actual);
25+
initialised.current = true;
26+
if (actual !== theme) setTheme(actual);
27+
// eslint-disable-next-line react-hooks/exhaustive-deps
2728
}, []);
2829

29-
// Keep <html> class and localStorage in sync whenever theme changes
30+
// Keep <html> class and localStorage in sync — but skip the very first run
31+
// (when theme is still the SSR default and initialised is not yet true).
3032
useEffect(() => {
33+
if (!initialised.current) return;
3134
const root = document.documentElement;
3235
if (theme === "dark") {
3336
root.classList.add("dark");

0 commit comments

Comments
 (0)