Next.js服务端渲染下获取localStorage用户信息的方案咨询
Next.js SSR中访问localStorage获取用户信息的解决方案
你的代码报错是因为Next.js服务端渲染阶段运行在Node.js环境,没有localStorage对象,而你直接在Redux slice的初始化逻辑里调用了localStorage.getItem,导致服务端执行时抛出ReferenceError。
下面是具体的解决方法和代码修改:
核心思路
将读取localStorage的逻辑限制在客户端浏览器环境中执行,避免服务端运行时访问不存在的API。
1. 修改Redux Slice,移除服务端的localStorage调用
首先把初始状态中的user设为null,添加一个专门用于从localStorage同步用户信息的reducer:
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit"; import authService from "./authService"; // 初始状态不再直接读取localStorage const initialState = { user: null, isError: false, isLoading: false, isSuccess: false, message: "", }; export const login = createAsyncThunk('auth/login', async (userData, thunkAPI) => { try { const response = await authService.login(userData); // 登录成功后将用户信息存入localStorage if (typeof window !== 'undefined') { localStorage.setItem("user", JSON.stringify(response)); } return response; } catch (error) { return thunkAPI.rejectWithValue(error.response?.data || error.message); } }); export const authSlice = createSlice({ name: "auth", initialState, reducers: { // 添加从localStorage同步用户的reducer syncUserFromLocalStorage: (state) => { if (typeof window !== 'undefined') { const savedUser = localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : null; state.user = savedUser; } }, // 可选:添加登出时清除localStorage的reducer logout: (state) => { if (typeof window !== 'undefined') { localStorage.removeItem("user"); } state.user = null; state.isSuccess = false; } }, extraReducers: (builder) => { builder .addCase(login.pending, (state) => { state.isLoading = true; state.isError = false; }) .addCase(login.fulfilled, (state, action) => { state.isLoading = false; state.isSuccess = true; state.user = action.payload; state.isError = false; }) .addCase(login.rejected, (state, action) => { state.isLoading = false; state.isError = true; state.isSuccess = false; state.user = null; state.message = action.payload; }); }, }); // 导出新增的reducer方法 export const { syncUserFromLocalStorage, logout } = authSlice.actions; export default authSlice.reducer;
2. 在客户端全局组件中触发同步逻辑
在Next.js的_app.js(或App Router下的layout.js)中,使用useEffect在客户端渲染时触发同步用户信息的action:
import { useEffect } from 'react'; import { useDispatch } from 'react-redux'; import { syncUserFromLocalStorage } from '../features/auth/authSlice'; function MyApp({ Component, pageProps }) { const dispatch = useDispatch(); // 仅在客户端执行,同步localStorage中的用户信息到Redux useEffect(() => { dispatch(syncUserFromLocalStorage()); }, [dispatch]); return <Component {...pageProps} />; } export default MyApp;
其他可选方案
- 使用客户端组件(App Router):如果是Next.js 13+ App Router,可将需要访问localStorage的组件标记为客户端组件(添加
'use client'指令),组件内直接读取localStorage即可。 - 动态导入禁用SSR:对于Pages Router,使用
dynamic导入组件时设置ssr: false,确保组件仅在客户端渲染:import dynamic from 'next/dynamic'; const AuthComponent = dynamic(() => import('../components/AuthComponent'), { ssr: false });
关键注意事项
- 任何访问
window、localStorage、sessionStorage等浏览器API的逻辑,都要通过typeof window !== 'undefined'判断环境,避免服务端报错。 - 登录成功后务必将用户信息存入
localStorage,确保刷新页面后能恢复登录状态。
内容的提问来源于stack exchange,提问作者nishikant singh
相关产品推荐
相关产品推荐

