使用React Context管理暗黑模式状态遇错误及状态不持久问题
问题修复方案
一、先解决Context报错问题
你遇到的警告是因为DarkModeContext.Consumer的使用方式错误——它要求子元素必须是一个函数,用来接收Context传递的值,但你直接放了<Router>组件。而且更合理的做法是让DarkModeProvider包裹整个应用,这样所有子组件都能通过useContext直接访问状态,不需要在App里手动写Consumer。
修改步骤:
调整根渲染结构:
在root.render中,把DarkModeProvider放在最外层,确保所有组件都能获取Context:const container = document.getElementById('example'); const root = createRoot(container); root.render( <DarkModeProvider> <UserProvider> <App /> </UserProvider> </DarkModeProvider> );简化App组件:
移除App里的DarkModeContext.Consumer,直接返回Router即可:const App = () => { return ( <Router> <Switch> <Route exact path="/" component={Home} /> <ProtectedRoute path="/settings" component={Settings} /> </Switch> </Router> ); }
二、实现暗黑模式状态持久化
之前状态丢失是因为useState的初始值是固定的true,页面刷新或导航后会重置。我们可以用localStorage来持久化状态,修改DarkModeContext.js:
import React, { createContext, useState, useEffect } from 'react'; export const DarkModeContext = createContext(); export const DarkModeProvider = ({ children }) => { // 从localStorage读取上次保存的状态,默认开启暗黑模式 const [darkModeChecked, setDarkModeChecked] = useState(() => { const savedMode = localStorage.getItem('darkMode'); return savedMode ? JSON.parse(savedMode) : true; }); const toggleDarkMode = () => { setDarkModeChecked((prev) => !prev); }; // 状态变化时自动保存到localStorage,同时全局更新body背景色 useEffect(() => { localStorage.setItem('darkMode', JSON.stringify(darkModeChecked)); document.body.style.backgroundColor = darkModeChecked ? 'black' : 'white'; }, [darkModeChecked]); return ( <DarkModeContext.Provider value={{ darkModeChecked, toggleDarkMode }}> {children} </DarkModeContext.Provider> ); };
可选优化:
你可以把Settings.js里的useEffect删掉,因为现在已经在Provider里全局处理了body背景色,避免重复逻辑:
// Settings.js 中移除这段代码 // useEffect(() => { // document.body.style.backgroundColor = darkModeChecked ? 'black' : 'white'; // }, [darkModeChecked]);
验证效果
现在切换明暗模式后,状态会自动存在localStorage里,刷新页面或跳转到其他组件时,会读取保存的状态,不会恢复浅色模式,同时之前的Context警告也会消失。
内容的提问来源于stack exchange,提问作者sp92
相关产品推荐
相关产品推荐

