Next.js Discord

Discord Forum

how do I check the theme of the 'system' without manually checking the window?

Unanswered
Chum salmon posted this in #help-forum
Open in Discord
Chum salmonOP
export function ModeToggle() {
  const {theme, setTheme} = useTheme();

  const isDarkMode = () => window.matchMedia('(prefers-color-scheme: dark)').matches;

  return (
    <DropdownMenu>
      <DropdownMenuTrigger>
        {theme === 'light' || (theme === 'system' && !isDarkMode()) ? (
          <SunIcon className="h-[1.2rem] w-[1.2rem] text-neutral-800 dark:hidden dark:text-neutral-200"/>
        ) : theme === 'dark' || (theme === 'system' && isDarkMode()) ? (
          <MoonIcon className="hidden h-[1.2rem] w-[1.2rem] text-neutral-800 dark:block dark:text-neutral-200"/>
        ) : null}
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <DropdownMenuItem
          onClick={() => setTheme("light")}
        >
          <span>Light</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("dark")}
        >
          <span>Dark</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("system")}
        >
          <span>System</span>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

39 Replies

Chum salmonOP
getting a hydration error
Error: Hydration failed because the initial UI does not match what was rendered on the server. See more info here: https://nextjs.org/docs/messages/react-hydration-error

<ModeToggle>
                        <DropdownMenu>
                          <Provider>
                            <Menu>
                              <Popper>
                                <Provider>
                                  <Provider>
                                    <Provider>
                                      <eval>
                                        <eval>
                                          <eval>
                                            <eval>
                                              <eval>
                                                <eval>
                                                  <eval>
                                                    <button>
                                                    ^^^^^^^^
                                                      <eval>
                                                        <svg>
                                                        ^^^^^
put the isDarkMode in a useEffect and state @Chum salmon
Chum salmonOP
oh :blob_facepalm:
thanks
@Chum salmon thanks
np, did it fix?
@Arinji np, did it fix?
Chum salmonOP
nah it didnt
"use client";

import { MoonIcon, SunIcon } from "@radix-ui/react-icons";
import { useTheme } from "next-themes";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { useEffect, useState } from "react";

export function ModeToggle() {
  const {theme, setTheme} = useTheme();

  const [darkMode, setDarkMode] = useState(false);

  useEffect(() => {
    const checkDarkMode = () => {
      setDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches);
    };

    checkDarkMode();
  }, []);

  return (
    <DropdownMenu>
      <DropdownMenuTrigger>
        {theme === 'light' || (theme === 'system' && !darkMode) ? (
          <SunIcon className="h-[1.2rem] w-[1.2rem] text-neutral-800 dark:hidden dark:text-neutral-200"/>
        ) : theme === 'dark' || (theme === 'system' && darkMode) ? (
          <MoonIcon className="hidden h-[1.2rem] w-[1.2rem] text-neutral-800 dark:block dark:text-neutral-200"/>
        ) : null}
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <DropdownMenuItem
          onClick={() => setTheme("light")}
        >
          <span>Light</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("dark")}
        >
          <span>Dark</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("system")}
        >
          <span>System</span>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
my code wrong or somethin
Chum salmonOP
yea
I could just suppress them everythings working as intended :shrug:
can you remove useTheme, and ust hardcode something?
Chum salmonOP
wym
I think its something to do with the Icons
const {theme, setTheme} = useTheme();
remove that
and hardcode its return
@Arinji const {theme, setTheme} = useTheme();
Chum salmonOP
fixed it
  const [mounted, setMounted] = useState(false);

  const isDarkMode = () => window.matchMedia('(prefers-color-scheme: dark)').matches;

  useEffect(() => {
    setMounted(true);
  }, []);

  if (!mounted) {
    return null;
  }
needed to wait 4 mounting
is that the best way of doing that
Chum salmonOP
lazy loading?
haven't done that before
try it out, you can like disable ssr importing
https://nextjs-forum.com/post/1245774952955646073#message-1245781128183418890

Another person had a similar issue i helped them with
@Arinji try it out, you can like disable ssr importing
Chum salmonOP
"use client";

import { MoonIcon, SunIcon } from "@radix-ui/react-icons";
import { useTheme } from "next-themes";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import dynamic from "next/dynamic";

const ModeToggleComponent = () => {
  const {theme, setTheme} = useTheme();

  const isDarkMode = () => window.matchMedia('(prefers-color-scheme: dark)').matches;

  return (
    <DropdownMenu>
      <DropdownMenuTrigger>
        {theme === 'light' || (theme === 'system' && !isDarkMode()) ? (
          <SunIcon className="h-[1.2rem] w-[1.2rem] text-neutral-800 dark:hidden dark:text-neutral-200"/>
        ) : theme === 'dark' || (theme === 'system' && isDarkMode()) ? (
          <MoonIcon className="hidden h-[1.2rem] w-[1.2rem] text-neutral-800 dark:block dark:text-neutral-200"/>
        ) : null}
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <DropdownMenuItem
          onClick={() => setTheme("light")}
        >
          <span>Light</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("dark")}
        >
          <span>Dark</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("system")}
        >
          <span>System</span>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}

const ModeToggle = dynamic(() => Promise.resolve(ModeToggleComponent), { ssr: false });

export default ModeToggle;
like this? this works
hmm wow thats an intresting way to use it
Chum salmonOP
just gpting it tbh 😭
but no, i was thinking something like this one sec
Chum salmonOP
how would you reccomend doing it
"use client";

import dynamic from 'next/dynamic';
import { MoonIcon, SunIcon } from "@radix-ui/react-icons";
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu";
import { useEffect, useState } from "react";

// Import useTheme with SSR disabled
const useTheme = dynamic(() => import("next-themes").then(mod => mod.useTheme), { ssr: false });

export function ModeToggle() {
  const { theme, setTheme } = useTheme();
  const [darkMode, setDarkMode] = useState(false);

  useEffect(() => {
    const checkDarkMode = () => {
      setDarkMode(window.matchMedia('(prefers-color-scheme: dark)').matches);
    };

    checkDarkMode();
  }, []);

  return (
    <DropdownMenu>
      <DropdownMenuTrigger>
        {theme === 'light' || (theme === 'system' && !darkMode) ? (
          <SunIcon className="h-[1.2rem] w-[1.2rem] text-neutral-800 dark:hidden dark:text-neutral-200"/>
        ) : theme === 'dark' || (theme === 'system' && darkMode) ? (
          <MoonIcon className="hidden h-[1.2rem] w-[1.2rem] text-neutral-800 dark:block dark:text-neutral-200"/>
        ) : null}
      </DropdownMenuTrigger>
      <DropdownMenuContent>
        <DropdownMenuItem
          onClick={() => setTheme("light")}
        >
          <span>Light</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("dark")}
        >
          <span>Dark</span>
        </DropdownMenuItem>
        <DropdownMenuItem
          onClick={() => setTheme("system")}
        >
          <span>System</span>
        </DropdownMenuItem>
      </DropdownMenuContent>
    </DropdownMenu>
  );
}
try this out
Chum salmonOP
Error: Unsupported Server Component type: undefined
@Arinji