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

Next.js SSR进入404页面后返回时出现属性未定义问题

问题分析与解决方案

你的问题不是导航组件导致的,核心原因是SSR页面拿到的服务端数据没有同步到客户端的useUser上下文里:

  1. 首次SSR加载时,getServerSideProps返回的user会被用于服务端渲染页面,此时上下文可能已注入user,页面正常显示;
  2. 从404页面通过Link导航回SSR页面时,客户端会请求服务器执行getServerSideProps并返回user props,但页面组件未将该props同步到useUser上下文,导致useUser()拿到的user为undefined,触发user!.id的属性未定义错误。

修复步骤

1. 修改SSR页面组件,同步服务端props到上下文

让MeSSR组件接收服务端返回的user props,并在客户端挂载时同步到上下文:

import { useUser } from "../context/user.context";
import { FC, useEffect } from 'react'
import { GetServerSidePropsContext } from "next";
import { fetcherSSR } from "../lib/fether-ssr";

// 定义页面props类型,建议替换为实际的user类型
type MeSSRProps = {
  user: { id: string };
};

const MeSSR: FC<MeSSRProps> = ({ user }) => {
  const { setUser } = useUser();

  // 客户端挂载时同步服务端返回的user到上下文
  useEffect(() => {
    if (user) {
      setUser(user);
    }
  }, [user, setUser]);

  // 增加加载判断,避免客户端hydrate阶段的错误
  if (!user) {
    return <div>Loading...</div>;
  }

  return (
    <main className="flex items-center justify-center h-full">
      <div className="text-center space-y-4">
        <h1 className="px-4 py-2 text-lg font-medium bg-gray-200 rounded">
          Server side authentication
        </h1>
        <p>Hi, {user.id} 👋</p>
      </div>
    </main>
  )
}

export default MeSSR

export const getServerSideProps = async (ctx: GetServerSidePropsContext) => {
    const {req, res} = ctx;
    const [error, user] = await fetcherSSR(req, res, 'http://localhost:3000/user/profile')

    if(!user) return {redirect: {statusCode:307, destination: '/login'}}
    return {props:{user}}
}

2. 优化UserContext支持服务端初始化(可选)

如果你的user.context是基础的createContext实现,建议在_app.tsx中通过页面props传递初始user,确保服务端渲染和客户端hydrate的数据一致:

// _app.tsx
import { UserProvider } from "../context/user.context";
import type { AppProps } from 'next/app'

function MyApp({ Component, pageProps }: AppProps) {
  return (
    <UserProvider initialUser={pageProps.user}>
      <Component {...pageProps} />
    </UserProvider>
  )
}

export default MyApp

修改user.context.ts,支持初始值注入:

import { createContext, useContext, useState } from 'react';

type User = {
  id: string;
  // 补充其他user属性
};

type UserContextType = {
  user: User | null;
  setUser: (user: User | null) => void;
};

const UserContext = createContext<UserContextType | undefined>(undefined);

export function UserProvider({ children, initialUser }: { children: React.ReactNode; initialUser?: User }) {
  const [user, setUser] = useState<User | null>(initialUser || null);

  return (
    <UserContext.Provider value={{ user, setUser }}>
      {children}
    </UserContext.Provider>
  );
}

export function useUser() {
  const context = useContext(UserContext);
  if (context === undefined) {
    throw new Error('useUser must be used within a UserProvider');
  }
  return context;
}

为什么导航组件没问题?

你的导航组件使用next/link的逻辑是正确的:Link触发客户端导航时,Next.js会自动向服务器请求执行getServerSideProps并获取页面数据,导航本身不存在问题。

内容的提问来源于stack exchange,提问作者Firdaus Ismail

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 08:10:29