My application has a theme change functionality (the theme itself is in the zustand store where persist is used). When updating the site, I need to get the theme out quickly to recolor ApplicationLoading to the desired color.
My code:
// page.tsx (Global layout, which connects in layout.tsx)
"use client";
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
import { useGetNewTokens } from "./hooks/usetGetNewTokens";
import { ApplicationLoader, LayoutSidebar } from "./components";
import type { ReactNode } from "react";
import { SocketProvider } from "./SocketProvider";
import { useSetTheme } from "./hooks/useSetTheme";
const queryClient = new QueryClient();
function Layout({ children }: { children: ReactNode }) {
useSetTheme();
const isLoading = useGetNewTokens();
if (isLoading) return <ApplicationLoader />;
return (
<SocketProvider>
<QueryClientProvider client={queryClient}>
<LayoutSidebar />
<div className="w-full">{children}</div>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
</SocketProvider>
);
}
export default Layout;
// useSetTheme.ts
"use client";
import { useSettingsStore } from "@/src/stores/useSettingsStore";
import type { Themes } from "@/src/types/general/theme";
import { useEffect } from "react";
function changeGlobalTheme(theme: Themes) {
document.body.setAttribute("data-theme", theme);
}
export const useSetTheme = () => {
const theme = useSettingsStore((state) => state.theme);
changeGlobalTheme(theme);
useEffect(() => {
changeGlobalTheme(theme);
}, [theme]);
};
Basically, in dev-mode then everything works, but in the VSCode terminal I get the following:
⨯ srccomponentslayouthooksuseSetTheme.ts (8:3) @ document
⨯ ReferenceError: document is not defined
at changeGlobalTheme (./src/components/layout/hooks/useSetTheme.ts:11:5)
at useSetTheme (./src/components/layout/hooks/useSetTheme.ts:15:5)
at Layout (./src/components/layout/page.tsx:23:68)
digest: "2077598245"
6 |
7 | function changeGlobalTheme(theme: Themes) {
> 8 | document.body.setAttribute("data-theme", theme);
| ^
9 | }
10 |
11 | export const useSetTheme = () => {
GET /settings/theme 500 in 70ms
Does anyone know how to fix this? The whole purpose of useSetTheme was to avoid the color “blinking” as it was when changeGlobalTheme()
was only in useEffect
. (If possible, please explain: I have "use client"
in <Layout />
, in useSetTheme
too, but still NextJS frowns).