Reputation: 4438
I am using React.js with Next.js, and I have 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 Next.js.
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?
Upvotes: 0
Views: 2265
Reputation: 181
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;
};
Upvotes: 2