0

I am using reactjs with nextjs, i am having the following problem. When the page is loaded I have to set a variable which should tell me if user is using dark mode or not.

I did the following, but I'm not sure if it's correct.

I had to set a value, because if I use window inside useState without using useEffect, it gives me problems with nextjs.

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

  useEffect(() => {
    setDarkMode(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
    const modeMe = (e) => {
      setDarkMode(!!e.matches);
    }
    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', modeMe);
    return window.matchMedia('(prefers-color-scheme: dark)').removeListener(modeMe);
  }, []);

or

const useDeviceMode = () => {
  const [darkMode, setDarkMode] = useState(false);
  useEffect(() => {
    setDarkMode(window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches)
    const modeMe = e => { setDarkMode(!!e.matches); }
    window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', modeMe);
    return window.matchMedia('(prefers-color-scheme: dark)').removeListener(modeMe);
  }, []);
  return [darkMode, setDarkMode]
}

  const [darkMode, setDarkMode] = useDeviceMode();

Can you give me some advice

Paul
  • 3,644
  • 9
  • 47
  • 113
  • What you did in the first code block seems correct. Next.js pre-renders all pages on the server, so any access to `window` should happen on the client-side only. – juliomalves Apr 07 '22 at 07:16

1 Answers1

1

Consider this snippet—

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

const modeMe = (e) => {
    setDarkMode(!!e.matches);
  };

useEffect(() => {
  const matchMedia = window.matchMedia("(prefers-color-scheme: dark)");
  
  setDarkMode(matchMedia.matches);
  matchMedia.addEventListener("change", modeMe);

  return () => matchMedia.removeEventListener("change", modeMe);
}, []);

Even better, come up with this custom hook—

import { useEffect, useState } from 'react';

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

  const modeMe = (e) => {
    setDarkMode(!!e.matches);
  };

  useEffect(() => {
    const matchMedia = window.matchMedia("(prefers-color-scheme: dark)");

    setDarkMode(matchMedia.matches);
    matchMedia.addEventListener("change", modeMe);

    return () => matchMedia.removeEventListener("change", modeMe);
  }, []);

  return darkMode;
};
Masterpage
  • 111
  • 1
  • 3