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

React主题切换器:页面刷新后主题选择无法持久的解决问询

主题刷新后不持久的解决方法

问题根源

你的代码存在三个核心问题导致主题无法在页面刷新后保持:

  1. localStorage 读写未正确处理序列化:直接读取localStorage.themes得到的是字符串,但你把它当成对象传给useState,初始值会无效;
  2. 对象引用比较逻辑错误:theme === themes.light是判断对象引用是否一致,而从localStorage解析出的对象和themes内的对象是不同引用,永远不会相等;
  3. 冗余的存储操作:每次组件渲染都会执行localStorage.setItem,逻辑重复且可能覆盖正确值。

修改方案

1. 修正 theme-toggler.js

import React, { createContext, useState, useEffect } from "react";

export const themes = {
    light: {
        background: "#41A9EC",
        fontColor: '#FFF'
    },
    dark: {
        background: "#F9F9F9", // 修正原代码中无效的颜色值#F9F9
        fontColor: '#000'
    }
}

export const ThemeContext = createContext({})

export const ThemeProvider = (props) => {
    // 初始化时从localStorage读取并解析,无值则默认使用light主题
    const [theme, setTheme] = useState(() => {
        const savedTheme = localStorage.getItem('themes');
        return savedTheme ? JSON.parse(savedTheme) : themes.light;
    });

    // 仅当theme变化时,同步更新到localStorage
    useEffect(() => {
        localStorage.setItem('themes', JSON.stringify(theme));
    }, [theme]);

    return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
            {props.children}
        </ThemeContext.Provider>
    )
}

2. 修正 theme-toggler-button.js 的主题判断逻辑

由于对象引用无法直接比较,我们可以通过主题的唯一属性(比如背景色)来判断当前主题:

import React, { useContext } from "react"
import { ThemeContext, themes } from "../../context/theme-toggler"
import { Button } from "../button/button"

export const ThemeTogglerButton = () => {
    const { theme, setTheme } = useContext(ThemeContext)
       
    return (
        <div style={{ backgroundColor: theme.background, color: theme.fontColor }}>
            <Button onClick={() => setTheme(theme.background === themes.light.background ? themes.dark : themes.light)}>
                Theme Toggler
            </Button>
        </div>
    )
}

额外优化建议

可以给每个主题添加name属性,让判断逻辑更清晰:

export const themes = {
    light: {
        name: 'light',
        background: "#41A9EC",
        fontColor: '#FFF'
    },
    dark: {
        name: 'dark',
        background: "#F9F9F9",
        fontColor: '#000'
    }
}

按钮中的判断可改为:

<Button onClick={() => setTheme(theme.name === 'light' ? themes.dark : themes.light)}>
    Theme Toggler
</Button>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 23:27:33