Reputation: 1048
I can use window.matchMedia
to detect whether user is in dark mode, but how to listen dark mode change event?
Is there any API like:
window.addEventListener('perfers-color-scheme-change', () => {
// do something
})
Upvotes: 50
Views: 19080
Reputation: 649
In React, a great way to do this is to create a custom hook like so
import React, {useEffect, useState} from 'react';
export const useTheme = () => {
const initialTheme = darkTheme;
const [theme, setTheme] = useState(initialTheme);
useEffect(() => {
const darkThemeListener = (e) => e.matches && setTheme(themes.dark);
const lightThemeListener = (e) => e.matches && setTheme(themes.light);
const mdark = window.matchMedia("(prefers-color-scheme: dark)");
const mlight = window.matchMedia("(prefers-color-scheme: light)");
mdark.addEventListener("change", darkThemeListener);
mlight.addEventListener("change", lightThemeListener);
return () => {
// cleanup event listeners
mdark.removeEventListener("change", darkThemeListener);
mlight.removeEventListener("change", lightThemeListener);
};
}, []);
return theme;
};
Upvotes: 5
Reputation: 9377
You can add an event-listener with callback on the MediaQueryList
returned by Window.matchMedia():
function activateDarkMode() {
// set style to dark
}
// MediaQueryList
const darkModePreference = window.matchMedia("(prefers-color-scheme: dark)");
// recommended method for newer browsers: specify event-type as first argument
darkModePreference.addEventListener("change", e => e.matches && activateDarkMode());
// deprecated method for backward compatibility
darkModePreference.addListener(e => e.matches && activateDarkMode());
Note: There are two method versions to register an event-listener:
addEventListener("change", listener))
which allows more fine-grained assignment to event-typesaddListener(listener)
Thanks to lukaszpolowczyk for pointing out that method addListener(listener)
has become deprecated and to AsukaSong for initiating a complete rewrite of this answer.
Upvotes: 63
Reputation: 431
With initialization setter and 'change' listener.
const colorSchemeQueryList = window.matchMedia('(prefers-color-scheme: dark)');
const setColorScheme = e => {
if (e.matches) {
// Dark
console.log('Dark mode')
} else {
// Light
console.log('Light mode')
}
}
setColorScheme(colorSchemeQueryList);
colorSchemeQueryList.addEventListener('change', setColorScheme);
Upvotes: 18