如何用TypeScript将暗黑/亮色模式状态持久化到LocalStorage?
解决React Context暗黑模式持久化及TypeScript类型错误问题
核心修复步骤
1. 读取LocalStorage作为初始状态(修复类型错误)
localStorage.getItem('Mode')返回string | null,直接传入JSON.parse会触发类型错误,同时要确保解析后的值是合法的boolean类型,避免非法值导致状态异常。可以封装初始化函数处理:
const getInitialDarkMode = (): boolean => { const storedMode = localStorage.getItem('Mode'); if (storedMode) { try { const parsedMode = JSON.parse(storedMode); // 验证解析结果为boolean,否则返回默认值 return typeof parsedMode === 'boolean' ? parsedMode : false; } catch (e) { // 解析失败时返回默认亮色模式 return false; } } // 无存储值时返回默认值 return false; };
在useState中调用该函数作为初始值:
const [darkMode, setDarkMode] = useState(getInitialDarkMode());
2. 模式切换时同步到LocalStorage
每次切换模式后,将最新状态存入LocalStorage,确保刷新页面后状态不丢失,有两种实现方式:
方式一:在切换函数中直接存储
const toggleMode = () => { setDarkMode(prevMode => { const newMode = !prevMode; localStorage.setItem('Mode', JSON.stringify(newMode)); return newMode; }); };
方式二:用useEffect监听状态变化
useEffect(() => { // darkMode变化时同步到LocalStorage localStorage.setItem('Mode', JSON.stringify(darkMode)); }, [darkMode]);
3. 优化TypeScript类型定义
- 将
TypeContext中的darkMode简化为boolean,与useState类型保持一致:
export interface TypeContext { darkMode: boolean; setDarkMode: React.Dispatch<React.SetStateAction<boolean>>; toggleMode: () => void; }
TypeChildrenProps的children改用React.ReactNode,支持多个子元素、文本等更灵活的场景:
export interface TypeChildrenProps { children: React.ReactNode; }
完整修正代码
import { createContext, useState, useEffect } from "react"; export interface TypeContext { darkMode: boolean; setDarkMode: React.Dispatch<React.SetStateAction<boolean>>; toggleMode: () => void; } export interface TypeChildrenProps { children: React.ReactNode; } export const GlobalThemeContext = createContext<TypeContext>({ darkMode: false, setDarkMode: () => {}, toggleMode: () => {}, }); const getInitialDarkMode = (): boolean => { const storedMode = localStorage.getItem('Mode'); if (storedMode) { try { const parsedMode = JSON.parse(storedMode); return typeof parsedMode === 'boolean' ? parsedMode : false; } catch (e) { return false; } } return false; }; export const ThemeContextProvider = ({ children }: TypeChildrenProps) => { const [darkMode, setDarkMode] = useState(getInitialDarkMode()); useEffect(() => { localStorage.setItem('Mode', JSON.stringify(darkMode)); }, [darkMode]); const toggleMode = () => { setDarkMode(!darkMode); }; return ( <GlobalThemeContext.Provider value={{ darkMode, setDarkMode, toggleMode }}> {children} </GlobalThemeContext.Provider> ); };
内容的提问来源于stack exchange,提问作者Pasha Mammadov
相关产品推荐
相关产品推荐

