You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React主题切换方案咨询:非Tailwind仅用SCSS,求类似next-themes的高性能库

适合React项目的主题切换方案(无Tailwind,基于SCSS)

推荐的主题切换库

1. use-dark-mode

  • 轻量级自定义Hook,专注处理深色/浅色模式切换,支持系统主题自动检测、本地存储持久化,API极简,完全适配SCSS变量体系。
  • 基础用法:
import useDarkMode from 'use-dark-mode';

function ThemeToggle() {
  const { value, toggle } = useDarkMode(false);
  return (
    <button onClick={toggle}>
      {value ? '切换到浅色模式' : '切换到深色模式'}
    </button>
  );
}

配合SCSS全局变量切换:

:root {
  --bg-color: #ffffff;
  --text-color: #1a1a1a;
}
.dark-mode {
  --bg-color: #1a1a1a;
  --text-color: #ffffff;
}
body {
  background-color: var(--bg-color);
  color: var(--text-color);
}

2. react-toggle-dark-mode

  • 自带切换按钮UI的小型库,封装了主题状态管理与持久化逻辑,无需手动编写按钮样式,可直接与SCSS变量配合使用。

替代next-themes的方案

如果偏好next-themes的全局上下文、系统主题同步、持久化等特性,可使用react-theme-provider——它是通用React生态的实现,不依赖Next.js,提供类似的上下文API:

  • 用法示例:
import { ThemeProvider, useTheme } from 'react-theme-provider';

const themes = {
  light: { bg: '#fff', text: '#000' },
  dark: { bg: '#000', text: '#fff' }
};

function App() {
  return (
    <ThemeProvider themes={themes} defaultTheme="light">
      <Content />
    </ThemeProvider>
  );
}

function Content() {
  const { theme, toggleTheme } = useTheme();
  return (
    <div style={{ backgroundColor: theme.bg, color: theme.text }}>
      <button onClick={toggleTheme}>切换主题</button>
    </div>
  );
}

配合SCSS时,可将主题变量注入根元素类名或内联样式中实现全局切换。

高性能手动实现方案

若不想引入额外依赖,手动实现的性能更可控,核心步骤如下:

1. 定义SCSS主题变量

// 浅色主题变量
$light-bg: #ffffff;
$light-text: #1a1a1a;

// 深色主题变量
$dark-bg: #1a1a1a;
$dark-text: #ffffff;

// 根元素变量映射
:root {
  --bg: #{$light-bg};
  --text: #{$light-text};
}

[data-theme="dark"] {
  --bg: #{$dark-bg};
  --text: #{$dark-text};
}

// 全局样式使用变量
body {
  background-color: var(--bg);
  color: var(--text);
  transition: background-color 0.3s, color 0.3s; // 可选过渡动画
}

2. 实现主题切换Hook

import { useState, useEffect } from 'react';

export function useTheme() {
  // 初始化主题:优先取本地存储,无则跟随系统主题
  const [theme, setTheme] = useState(() => {
    const saved = localStorage.getItem('theme');
    const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches;
    return saved || (prefersDark ? 'dark' : 'light');
  });

  // 切换主题逻辑
  const toggleTheme = () => {
    const newTheme = theme === 'light' ? 'dark' : 'light';
    setTheme(newTheme);
    localStorage.setItem('theme', newTheme);
    document.documentElement.setAttribute('data-theme', newTheme);
  };

  // 初始化时设置DOM属性
  useEffect(() => {
    document.documentElement.setAttribute('data-theme', theme);
  }, [theme]);

  // 监听系统主题变化(仅在未手动设置主题时生效)
  useEffect(() => {
    const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)');
    const handleChange = (e) => {
      if (!localStorage.getItem('theme')) {
        setTheme(e.matches ? 'dark' : 'light');
      }
    };
    mediaQuery.addEventListener('change', handleChange);
    return () => mediaQuery.removeEventListener('change', handleChange);
  }, []);

  return { theme, toggleTheme };
}

3. 在组件中使用

function ThemeToggle() {
  const { theme, toggleTheme } = useTheme();
  return (
    <button onClick={toggleTheme}>
      {theme === 'light' ? '🌙 深色模式' : '☀️ 浅色模式'}
    </button>
  );
}

高性能要点

  • 使用CSS原生变量:比JS动态修改DOM样式性能更高,浏览器原生支持样式切换。
  • 本地存储持久化:避免页面刷新后主题重置,无需重复判断。
  • 精准监听系统主题:仅在用户未手动设置主题时跟随系统,兼顾体验与用户选择。
  • 减少不必要重渲染:Hook仅在主题变化时更新状态,避免组件冗余渲染。

内容的提问来源于stack exchange,提问作者nkabe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 06:48:13