登录后切换主题触发Uncaught DOMException错误求助
主题切换报错:Uncaught DOMException: failed to execute add on DOMTokenList
出现错误 Uncaught DOMException: failed to execute add on DOMTokenList,该错误仅在Supabase认证登录后触发;清除浏览器缓存或使用无痕模式时,主题切换功能正常,推测问题与认证逻辑相关。
相关代码
1. navbar.jsx 主题切换逻辑与导航栏元素
// 明暗主题切换函数 const toggleTheme = () => { setTheme((prevTheme) => (prevTheme === "light" ? "dark" : "light")); };
<div id="navbar-container" className={`flex justify-between z-10 items-center top-0 pt-3 px-4 w-full sticky ${theme === "dark" ? "bg-slate-950": "bg-white"}`}>
2. App.jsx 中 shadcn-ui ThemeProvider 配置
const Navigation = () => { const location = useLocation(); const loginRoute = location.pathname === '/login'; const emailConfirmRoute = location.pathname === "/success/confirm"; // 根据路由决定渲染的导航栏组件 const renderNavbar = loginRoute || emailConfirmRoute ? null : (location.pathname === '/' ? <Navbar /> : <DashboardNavbar />); return renderNavbar; }; const FooterComponent = () => { const location = useLocation(); const loginRoute = location.pathname === '/login'; const renderFooter = loginRoute ? null : (location.pathname === '/' ? <Footer /> : null); return renderFooter; }; // 创建用户上下文 export const UserContext = createContext(null); // 自定义Hook以使用用户上下文 export const useUser = () => useContext(UserContext); const App = () => { const [user, setUser] = useState(null); // 通过useEffect获取认证会话状态 useEffect(() => { async function getSession() { try { const {data: { session }} = await supabase.auth.getSession() if (session) { console.log("Session object:", session); if (session.user && session.user.aud) { console.log("Session aud:", session.user?.aud) } else { console.log("Session is undefined") } setUser(session.user); } else { console.log('No active session: User is not logged in'); } } catch (error) { console.error('Error fetching session:', error); } } getSession(); }, [setUser]); return ( <ThemeProvider defaultTheme='light' storageKey='vite-ui-theme'> <UserContext.Provider value={{ user, setUser }}> <Router> <div> <Navigation/> <Routes> <Route path="/" element={<Home />} /> <Route path='/create' element={<Dashboard />} /> <Route path='/login' element={<Login />} /> <Route path='/success/confirm' element={<ConfirmEmail />} /> </Routes> <FooterComponent /> </div> </Router> </UserContext.Provider> </ThemeProvider> ); }; export default App;
3. themeProvider.jsx 实现
/* eslint-disable react/prop-types */ import { createContext, useContext, useEffect, useState } from "react"; const ThemeProviderContext = createContext(null); export function ThemeProvider({ children, defaultTheme = "system", storageKey = "vite-ui-theme", ...props }) { const [theme, setTheme] = useState( () => localStorage.getItem(storageKey) || defaultTheme ); useEffect(() => { const root = window.document.documentElement; root.classList.remove("light", "dark"); if (theme === "system") { const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") .matches ? "dark" : "light"; root.classList.add(systemTheme); return; } root.classList.add(theme); }, [theme]); const value = { theme, setTheme: (theme) => { localStorage.setItem(storageKey, theme); setTheme(theme); }, }; return ( <ThemeProviderContext.Provider {...props} value={value}> {children} </ThemeProviderContext.Provider> ); } // eslint-disable-next-line react-refresh/only-export-components export const useTheme = () => { const context = useContext(ThemeProviderContext); if (context === undefined) throw new Error("useTheme must be used within a ThemeProvider"); return context; };
内容的提问来源于stack exchange,提问作者anon
相关产品推荐
相关产品推荐

