Next.js项目访问localStorage和window报未定义错误如何解决
问题原因
Next.js默认会在服务端执行组件的渲染逻辑,而服务端环境没有浏览器提供的window、localStorage等全局对象,你直接在组件的顶层(return语句之前,渲染阶段)访问这些API,服务端渲染时就会抛出未定义的错误。
解决方案
以下是几种可直接落地的解决方式:
- 方案1:将浏览器API访问逻辑放到
useEffect回调中useEffect只会在组件挂载到客户端之后执行,此时已经处于浏览器环境,可以安全访问所有浏览器API。修改后的代码示例:
import moment from "moment"; import { useState, useEffect } from "react"; export default function Clicked() { const [passed, setPassed] = useState(false) // 新增state存储从localStorage读取的值 const [currentTime, setCurrentTime] = useState(null) const click = () => { const currentTime =moment().format('HH:mm:ss'); var endTime = moment().add(10, 'second').format('hh:mm:ss A') localStorage.setItem('currentTime', currentTime) localStorage.setItem('endTime', endTime) setCurrentTime(currentTime) console.log(endTime) console.log(currentTime) } // 组件挂载后读取本地存储的值 useEffect(() => { console.log(window) const storedTime = localStorage.getItem("currentTime"); setCurrentTime(storedTime) console.log('currentTime', storedTime) }, []) return( <> <button onClick={() => click()}>click</button> <h1>hello</h1> {/* 展示读取到的时间 */} {currentTime && <p>上次点击时间:{currentTime}</p>} </> ) }
- 方案2:访问前增加环境判断
如果需要在渲染阶段直接访问,可以先判断当前是否处于浏览器环境,再执行对应逻辑:
// 只有浏览器环境下才会执行后续逻辑 if (typeof window !== 'undefined') { console.log(window) const currentTime = localStorage.getItem("currentTime"); console.log('currentTime', currentTime) }
- 方案3:Next.js 13+ App Router场景增加客户端组件标记
如果你使用的是Next.js 13及以上版本的App Router,所有组件默认是服务端组件,无法访问浏览器API,需要在组件文件的第一行添加'use client'标记,声明该组件为客户端组件,再配合前两个方案使用即可。
内容的提问来源于stack exchange,提问作者Shahab Khan
相关产品推荐
相关产品推荐

