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

切换路由时@auth0/nextjs-auth0反复调用/me API问题求助

解决Next.js中Auth0切换路由时组件闪烁问题

问题根源

切换路由时,@auth0/nextjs-auth0的useUser hook会重新发起/me API请求,在请求完成前user会被重置为undefined,导致依赖user的导航菜单等组件暂时隐藏,出现闪烁。

解决方案

1. 服务器端预传用户会话

在_app.tsx中通过getServerSideProps从服务器端获取用户会话,直接传递给UserProvider,让客户端初始化时就拥有用户状态,避免等待/me请求。

修改_app.tsx:

import "../styles/globals.css";
import type { AppProps } from "next/app";
import { appWithTranslation } from "next-i18next";
import { UserProvider } from "@auth0/nextjs-auth0/client";
import AppMenu from "../components/AppMenu";
import { getSession } from "@auth0/nextjs-auth0";

function MyApp({ Component, pageProps }: AppProps) {
  return (
    // 直接传入服务器端获取的user,覆盖客户端初始状态
    <UserProvider user={pageProps.user}>
      <AppMenu>
          <Component {...pageProps} />
      </AppMenu>
    </UserProvider>
  );
}

export async function getServerSideProps(context: any) {
  // 从服务器端获取用户会话
  const session = await getSession(context.req, context.res);
  // 合并next-i18next的props
  const i18nProps = await appWithTranslation.getServerSideProps(context);
  
  return {
    props: {
      user: session?.user || null,
      ...i18nProps.props
    }
  };
}

export default appWithTranslation(MyApp);

2. 调整组件的状态判断

修改AppMenu组件,将判断逻辑从user && ...改为user !== null && ...,因为现在初始user值是服务器传递的null(未登录)或用户对象,不再是undefined:

import { NextPage } from "next";
import { useUser } from "@auth0/nextjs-auth0/client";

interface Props {
  children: JSX.Element;
}

const AppMenu: NextPage<Props> = ({ children }) => {
  const { user } = useUser();
  
  return (
    <div>
      {user !== null && (<nav>{/* 原有导航内容 */}</nav>) }
      {children}
    </div>
  );
};

export default AppMenu;

原理说明

通过服务器端预取用户会话,UserProvider在客户端初始化时就拥有了用户状态的初始值,不会在路由切换时先回到undefined。后续/me请求只会用于验证会话有效性,但初始渲染时已经有可用的用户数据,避免了组件闪烁。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 09:10:40