React主题切换器:页面刷新后主题选择无法持久的解决问询
主题刷新后不持久的解决方法
问题根源
你的代码存在三个核心问题导致主题无法在页面刷新后保持:
- localStorage 读写未正确处理序列化:直接读取
localStorage.themes得到的是字符串,但你把它当成对象传给useState,初始值会无效; - 对象引用比较逻辑错误:
theme === themes.light是判断对象引用是否一致,而从localStorage解析出的对象和themes内的对象是不同引用,永远不会相等; - 冗余的存储操作:每次组件渲染都会执行
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
相关产品推荐
相关产品推荐

