NextJS 14中基于localStorage实现暗黑模式时遇到未定义错误及取值为null的问题求助
NextJS 14中基于localStorage实现暗黑模式时遇到未定义错误及取值为null的问题求助
嗨,我来帮你搞定这个问题!你碰到的两个状况——终端报ReferenceError: localStorage is not defined,还有首次加载时console.log出null,其实都是Next.js 14的服务器端渲染(SSR)特性导致的,咱们一步步拆解解决:
问题根源
- Next.js默认会做服务器端渲染,而
localStorage是浏览器专属的API,服务器环境里根本没有这个对象,所以你在组件顶层直接调用localStorage.getItem()初始化state时,服务器端执行就会报错。 - 首次加载时
localStorage.getItem("theme")返回null,是因为这时候浏览器的localStorage里还没存储过theme这个键值对,直接取值自然是null。
解决方案
我给你调整了代码,每一处改动都标注了原因:
"use client"; import { useEffect, useState } from "react"; export default function Darkmode() { // 1. 用函数式初始化state,先判断是否在浏览器环境(避免服务器端报错) // 同时兜底默认值为"light",解决首次加载null的问题 const [theme, setTheme] = useState(() => { if (typeof window !== 'undefined') { return localStorage.getItem("theme") || "light"; } // 服务器端渲染时默认返回light,保证SSR阶段不报错 return "light"; }); const handleTheme = (e) => { setTheme(e.target.checked ? "dark" : "light"); }; useEffect(() => { // 2. 同样先判断浏览器环境,确保只在客户端执行localStorage和DOM操作 if (typeof window !== 'undefined') { localStorage.setItem("theme", theme); document.querySelector("html").setAttribute("data-theme", theme); } }, [theme]); // 3. 把console.log移到useEffect里,确保只在客户端执行,避免服务器端报错 useEffect(() => { if (typeof window !== 'undefined') { console.log(localStorage.getItem("theme")); } }, []); return ( <> {/* 这里放你的组件内容,比如切换开关 */} <label> <input type="checkbox" checked={theme === "dark"} onChange={handleTheme} /> 开启暗黑模式 </label> </> ); }
关键改动说明
- 函数式初始化state:避免组件在服务器端渲染时直接调用
localStorage,同时用|| "light"兜底,解决首次加载取值为null的问题。 - 添加浏览器环境判断:所有涉及
localStorage和DOM操作的代码,都先判断typeof window !== 'undefined',确保只在客户端执行。 - 优化console.log位置:把日志输出移到
useEffect中,保证只在浏览器端执行,不会触发服务器端报错。
这样修改后,你应该就不会再遇到未定义错误,首次加载也会默认使用light主题,切换后localStorage也能正确存储啦!
备注:内容来源于stack exchange,提问作者Amit Deka
相关产品推荐
相关产品推荐

