Lazy initialization w React dla przełącznika motywu
Pokazujemy, jak używać lazy initialization w React z uwzględnieniem SSR, cookies, testów A/B i pamięci przeglądarki użytkownika.
1. Dlaczego lazy initialization?
Reactowe useState przyjmuje funkcję inicjalizującą, która wykonuje się tylko raz podczas pierwszego renderu. Dokumentacja (docs/react-useState-lazy-initialization.md) pokazuje, że to świetny sposób na pobranie motywu z localStorage i uniknięcie dodatkowych renderów. Rozszerzmy tę technikę o inne scenariusze.
2. Standardowy Dark Mode (localStorage)
const [isDark, setIsDark] = useState(() => {
const saved = localStorage.getItem("theme");
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
return saved === "dark" || (!saved && prefersDark);
});
Pierwszy render od razu zna poprawny motyw, więc nie ma migotania.
3. SSR + Hydration
Na serwerze nie mamy window. Zabezpiecz się przed tym:
const [isDark, setIsDark] = useState(() => {
if (typeof window === "undefined") {
return false; // domyślny motyw dla SSR
}
const saved = localStorage.getItem("theme");
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
return saved === "dark" || (!saved && prefersDark);
});
4. Cookies (np. multi-device sync)
import Cookies from "js-cookie";
const [isDark, setIsDark] = useState(() => {
if (typeof window === "undefined") return false;
const cookie = Cookies.get("theme");
if (cookie) return cookie === "dark";
const prefersDark = window.matchMedia("(prefers-color-scheme: dark)").matches;
return prefersDark;
});
useEffect(() => {
Cookies.set("theme", isDark ? "dark" : "light", { expires: 365 });
}, [isDark]);
Cookie synchronizuje motyw między przeglądarkami i urządzeniami.
5. sessionStorage (formularze)
const [isDark, setIsDark] = useState(() => {
if (typeof window === "undefined") return false;
const saved = sessionStorage.getItem("theme");
return saved ? saved === "dark" : false;
});
useEffect(() => {
sessionStorage.setItem("theme", isDark ? "dark" : "light");
}, [isDark]);
Przydatne w panelach administracyjnych, gdzie chcesz pamiętać motyw na czas sesji.
6. A/B test – przechowywanie wariantu
const getVariant = () => {
if (typeof window === "undefined") return "control";
const stored = localStorage.getItem("theme_variant");
if (stored) return stored;
const variant = Math.random() > 0.5 ? "control" : "experiment";
localStorage.setItem("theme_variant", variant);
return variant;
};
const [variant] = useState(getVariant);
const initialDark = variant === "experiment";
const [isDark, setIsDark] = useState(() => {
if (typeof window === "undefined") return initialDark;
const saved = localStorage.getItem("theme");
return saved ? saved === "dark" : initialDark;
});
Wariant decyduje o domyślnym motywie, a lazy init gwarantuje, że wylosujesz go tylko raz.
7. SSR + klastry CDN (wersja Hermes)
Jeśli odczytujesz dane z window.__INITIAL_DATA__, użyj lazy init, by nie dekodować JSON na każdym renderze:
const [initialTheme] = useState(() => {
if (typeof window === "undefined") return "light";
const data = (window as any).__INITIAL_DATA__;
return data?.theme ?? "light";
});
const [isDark, setIsDark] = useState(() => initialTheme === "dark");
8. Podsumowanie
- Zawsze otaczaj kod warunkiem
typeof window !== "undefined"w środowisku SSR. - Lazy initialization zapobiega migotaniu i zbędnym renderom.
- Zmieniaj storage (
localStorage,sessionStorage, cookies) zależnie od potrzeb biznesowych. - Przetwarzanie A/B i danych wstępnych (SSR) to kolejne przypadki, w których funkcja inicjalizująca robi różnicę.
Usprawnione zarządzanie motywem to wyższy komfort użytkownika i mniej pracy nad łagodzeniem efektów ubocznych w interfejsie.
📚 Dokumentacja i Zasoby
Oficjalna Dokumentacja
Powiązane Artykuły
Podobał Ci się ten artykuł?
Udostępnij go osobom, którym ten materiał może się przydać.
Powiązane artykuły
Automatyzacja frontendu: Plan Mode i hook PostToolUse
Sprawdź, jak skonfigurować Claude Code, aby planował zmiany, formatował kod, uruchamiał `astro check` i wskazywał brakujące testy.
Hooki Claude Code jako lekkie CI dla frontendu
Budujemy zestaw hooków PostToolUse i Stop, które po każdej zmianie formatują kod, uruchamiają testy i przygotowują raport jakości.