React迁移Next.js时提示localStorage is not defined怎么解决?
问题解决方案
问题根源是Next.js服务端渲染阶段没有window对象,自然不存在localStorage,你代码里useState的初始化回调会在服务端渲染组件时直接执行,因此触发报错。
方案1:将localStorage读取逻辑移入useEffect
useEffect仅在客户端挂载后执行,天然避开服务端环境,修改后的状态初始化代码如下:
import { useState, useEffect } from 'react' import jwt_decode from 'jwt-decode' // 组件内代码 // 初始值先设为null const [authTokens, setAuthTokens] = useState(null) const [user, setUser] = useState(null) useEffect(() => { // 客户端执行时读取localStorage const storedTokens = localStorage.getItem('authTokens') if (storedTokens) { const parsedTokens = JSON.parse(storedTokens) setAuthTokens(parsedTokens) setUser(jwt_decode(parsedTokens.access)) } }, [])
登录函数本身是用户交互触发的事件回调,仅会在客户端执行,原有逻辑无需修改,稳妥起见也可以加环境判断:
if(response.status == 200) { setAuthTokens(data) setUser(jwt_decode(data.access)) // 加环境判断兼容极端情况 if (typeof window !== 'undefined') { localStorage.setItem('authTokens', JSON.stringify(data)) } router.push('/') }
方案2:封装localStorage安全访问工具
如果项目中多处用到localStorage,可以统一封装工具函数避免重复判断:
// 新建utils/storage.js export const safeLocalStorage = { getItem: (key) => { if (typeof window === 'undefined') return null return localStorage.getItem(key) }, setItem: (key, value) => { if (typeof window === 'undefined') return localStorage.setItem(key, value) }, removeItem: (key) => { if (typeof window === 'undefined') return localStorage.removeItem(key) } }
后续所有操作localStorage的地方都替换为该工具即可:
// 初始化也可以直接用,服务端会自动返回null const [authTokens, setAuthTokens] = useState(() => safeLocalStorage.getItem('authTokens') ? JSON.parse(safeLocalStorage.getItem('authTokens')) : null)
Next.js 13+ App Router额外注意
如果使用App Router,需要在使用localStorage的组件顶部添加'use client'标记,标记该组件为客户端组件,再配合上述两种方案即可。
内容的提问来源于stack exchange,提问作者devAR
相关产品推荐
相关产品推荐

