You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 15:22:45