Skip to main content

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.

  1. 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>
  1. 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

PropertyDescriptionTypeDefaultValue
selectorCSS Selector for the target element applying tostring'html'
attributeHTML attribute applying the target elementstring'class'
defaultValuedefault valuebooleanfalse
storageKeyKey to persist the data into localStorage/sessionStorage.string'reactuses-color-scheme'
storageStorage object, can be localStorage or sessionStorage() => StoragelocalStorage
classNameDarkname dark apply to elementstring (Required)-
classNameLightname light apply to elementstring (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

ArgumentDescriptionTypeDefaultValue
options-UseDarkOptions (Required)-