useDarkMode
dark mode with auto data persistence.
Tips
click to open
For server-side rendered applications, since it's not possible to obtain the user's color preference on the server side, there might be a flicker during the first render. To avoid this issue, you can refer to the following steps.
- add a script before your content.
<script
dangerouslySetInnerHTML={{
// 增加一个自执行的函数
__html: `
(function () {
function setDark(dark) {
dark && document.documentElement.classList.add('dark');
}
let store;
try {
store = JSON.parse(localStorage.getItem('reactuses-color-scheme'));
} catch (err) { }
let dark;
if(store === null){
const darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
dark = darkQuery.matches;
}else {
dark = store;
}
setDark(dark)
})();
`,
}}
></script>
- To conveniently manage theme colors in a unified way, we recommend using context to store them.
import { useDarkMode } from "@reactuses/core";
import React, { createContext, useContext } from "react";
type ThemeContext = { theme: boolean; toggleTheme: () => void };
const ThemeContext = createContext<ThemeContext | undefined>(undefined);
export function ThemeProvider({ children }: { children: React.ReactNode }) {
const [dark, setDark] = useDarkMode({
classNameDark: "dark",
classNameLight: "light",
defaultValue: false,
});
return (
<ThemeContext.Provider value={{ theme: !!dark, toggleTheme: setDark }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error("useTheme must be used within a ThemeProvider");
}
return context;
}
Usage
Live Editor
function Demo() { const [theme, toggleDark] = useDarkMode({ classNameDark: "dark", classNameLight: "light", defaultValue: false, }); return ( <div> <div>theme: {theme ? "dark" : "light"}</div> <br /> <div> <button onClick={toggleDark}>toggleDark</button> </div> </div> ); }
Result
Loading...
API
UseDarkOptions
Property | Description | Type | DefaultValue |
---|---|---|---|
selector | CSS Selector for the target element applying to | string | 'html' |
attribute | HTML attribute applying the target element | string | 'class' |
defaultValue | default value | boolean | false |
storageKey | Key to persist the data into localStorage/sessionStorage. | string | 'reactuses-color-scheme' |
storage | Storage object, can be localStorage or sessionStorage | () => Storage | localStorage |
classNameDark | name dark apply to element | string (Required) | - |
classNameLight | name light apply to element | string (Required) | - |
useDarkMode
Returns
readonly [boolean | null, () => void, React.Dispatch<React.SetStateAction<boolean | null>>]
: A tuple with the following elements:
- The current value of the dark state.
- A function to toggle the dark state.
- A function to update the dark state.
Arguments
Argument | Description | Type | DefaultValue |
---|---|---|---|
options | - | UseDarkOptions (Required) | - |