---
title: "useDarkMode 用法与示例"
description: "具有自动数据持久性的深色模式。"
canonical: https://reactuse.com/zh-Hans/browser/usedarkmode/
---

# useDarkMode

具有自动数据持久性的深色模式。

## ⚠️ v6.1.0 破坏性变更

**存储格式已从布尔值更改为字符串值。** 如果你正在从旧版本升级：

- **旧格式**: `true`/`false` 布尔值
- **新格式**: `"dark"`/`"light"` 字符串值  
- **自动迁移**: 现有数据将自动迁移
- **SSR 脚本**: 需要更新以处理字符串比较

<details>
<summary>迁移指南</summary>

如果你有自定义的 SSR 脚本，请按照下面示例中的方式进行更新。库会自动处理数据迁移，但你的自定义脚本需要在过渡期间处理新旧两种格式。

</details>

## Tips

<details>
<summary>点击展开</summary>
对于服务端渲染的应用程序而言，由于无法在服务端获取到用户的颜色偏好。所以第一次渲染的时候可能会出现闪烁。想要避免此问题，你可以参考一下步骤。

1. 在你的内容渲染前增加一个脚本。

```tsx
<script
  dangerouslySetInnerHTML={{
    // 增加一个自执行的函数
    __html: `
          (function () {
            function setDark(dark) {
              dark &&  document.documentElement.classList.add('dark');
            }
            let store = localStorage.getItem('reactuses-color-scheme');
            let dark;
            if(store === null){
              const darkQuery = window.matchMedia('(prefers-color-scheme: dark)');
              dark = darkQuery.matches;
            }else {
              // 处理向后兼容性：将旧的布尔值转换为字符串
              if (store === 'true' || store === 'false') {
                const boolValue = store === 'true';
                const stringValue = boolValue ? 'dark' : 'light';
                localStorage.setItem('reactuses-color-scheme', stringValue);
                dark = boolValue;
              } else {
                // 直接处理字符串值 ('dark' 或 'light')
                dark = store === 'dark';
              }
            }
            setDark(dark)
          })();
      `,
  }}
></script>
```

2. 为了方便统一管理主题颜色，我们推荐使用 `context` 来存储它们。

```tsx
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, toggle] = useDarkMode({
    classNameDark: "dark",
    classNameLight: "light",
    defaultValue: false,
  });

  return (
    <ThemeContext.Provider value={{ theme: !!dark, toggleTheme: toggle }}>
      {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;
}
```

</details>

`useDarkMode` 提供简单的深色/浅色模式切换，并自动持久化到 `localStorage`。它返回一个包含当前主题状态和切换函数的元组。该 hook 将 CSS 类名（可配置为 `classNameDark` 和 `classNameLight`）应用到 `<html>` 元素，并在没有存储值时通过 `prefers-color-scheme` 媒体查询与用户的系统偏好同步。它以系统偏好为默认值，但允许用户覆盖。

### 使用场景

- 为应用添加带有自动持久化功能的深色模式切换
- 构建以用户系统颜色方案偏好为默认值的主题切换器
- 将深色/浅色 CSS 类应用到根元素，实现 CSS 驱动的主题切换

### 注意事项

- **SSR 安全**：在服务端渲染期间深色模式状态返回 `false`。服务端不会访问 DOM 或 localStorage。参见下方"技巧"部分了解如何防止未样式化内容的闪烁。
- **持久化**：将偏好存储在 `localStorage` 中，键名为 `"reactuses-color-scheme"`。存储的值会在 v6.1.0+ 中自动从旧的布尔格式迁移到新的字符串格式。
- **相关 hooks**：如需超越深色/浅色的多主题支持，参见 `useColorMode`。如需检测系统偏好但不进行持久化，参见 `usePreferredDark` 或 `usePreferredColorScheme`。

## Usage

```tsx live

function Demo() {
  const [theme, toggleDark] = useDarkMode({
    classNameDark: "dark",
    classNameLight: "light",
    defaultValue: false,
  });

  return (
    <div>
      <div>主题: {theme ? "深色" : "浅色"}</div>
      <br />
      <div>
        <button onClick={toggleDark}>切换深色模式</button>
      </div>
    </div>
  );
};

```

%%API%%