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

如何等待NextAuth会话加载?解决手动输入URL的Token读取报错问题

解决NextAuth页面刷新时session未加载导致的accessToken读取错误

问题场景

使用NextAuth实现用户认证,将accessToken存储在session中。在[trackId].js页面,通过useState的refresh状态变化触发useEffect获取最新曲目数据,正常操作无异常,但手动输入URL刷新页面时,出现如下错误:

TypeError: Cannot read properties of undefined (reading 'accessToken')

原因是页面刷新时session处于loading状态,session.data仍为undefined,accessToken尚未加载完成。

解决方案

方案1:组件层面处理session加载状态

在组件中通过useSession获取session的同时,判断loading状态,在session未加载完成前不渲染业务内容,避免触发错误请求:

import { useSession } from "next-auth/react";
import { useState, useEffect } from "react";

export default function TrackPage({ trackId }) {
  const { data: session, loading } = useSession();
  const [refresh, setRefresh] = useState(false);
  const [getedTrack, setGetedTrack] = useState(null);

  // 加载中时显示占位内容
  if (loading) return <div>加载中...</div>;
  // 未登录时跳转或提示
  if (!session) return <div>请先登录</div>;

  useEffect(() => {
    async function refreshPage() {
      await axiosPrivateWithToken(session.data.accessToken)
        .get(`/track/get/${trackId}`)
        .then((res) => setGetedTrack(res.data))
        .catch((error) => console.log("刷新曲目失败: ", error));
    }
    refreshPage();
  }, [refresh, session.data.accessToken]);

  // 页面核心渲染内容
  return <div>{/* 曲目展示内容 */}</div>;
}

方案2:在useEffect内校验session有效性

修改useEffect的依赖数组,加入session,并在请求前先校验accessToken是否存在,避免读取undefined属性:

useEffect(() => {
  async function refreshPage() {
    // 先校验session及accessToken的有效性
    if (!session?.data?.accessToken) {
      console.log("Session未就绪或用户未登录");
      return;
    }
    await axiosPrivateWithToken(session.data.accessToken)
      .get(`/track/get/${trackId}`)
      .then((res) => setGetedTrack(res.data))
      .catch((error) => console.log("刷新曲目失败: ", error));
  }
  refreshPage();
}, [refresh, session]); // 将session加入依赖,确保状态更新时重新执行

方案3:服务端预获取session(SSR方式)

通过getServerSideProps在服务端获取session,将accessToken作为props传递给页面,彻底避免客户端加载延迟问题:

import { getSession } from "next-auth/react";
import { useState, useEffect } from "react";

export async function getServerSideProps(context) {
  const session = await getSession(context);
  
  // 未登录时直接跳转登录页
  if (!session?.data?.accessToken) {
    return {
      redirect: {
        destination: "/login",
        permanent: false,
      },
    };
  }

  return {
    props: { accessToken: session.data.accessToken },
  };
}

export default function TrackPage({ trackId, accessToken }) {
  const [refresh, setRefresh] = useState(false);
  const [getedTrack, setGetedTrack] = useState(null);

  useEffect(() => {
    async function refreshPage() {
      await axiosPrivateWithToken(accessToken)
        .get(`/track/get/${trackId}`)
        .then((res) => setGetedTrack(res.data))
        .catch((error) => console.log("刷新曲目失败: ", error));
    }
    refreshPage();
  }, [refresh, accessToken]);

  return <div>{/* 曲目展示内容 */}</div>;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 17:05:59