如何让SWR等待Next Auth会话加载完成后再发起请求?
解决Next Auth会话同步延迟导致SWR提前请求的问题
核心思路是等待Next Auth完成会话状态同步后,再触发SWR的数据请求,以下是几种可行的实现方案:
方案一:利用useSession状态控制SWR请求时机
useSession钩子会返回会话的status状态(loading/authenticated/unauthenticated),我们可以通过这个状态配合SWR的enabled选项,控制请求仅在会话加载完成后发起:
import { useSession } from "next-auth/react"; import useSWR from "swr"; // 带身份验证的请求函数 const authFetcher = async (url, token) => { const res = await fetch(url, { headers: { Authorization: `Bearer ${token}` } }); if (!res.ok) throw new Error("数据请求失败"); return res.json(); }; function UserProfile() { const { data: session, status } = useSession(); // 仅当会话已认证时,才传入请求key并启用SWR const { data: userData, error } = useSWR( status === "authenticated" ? ["/api/user/profile", session.user.accessToken] : null, authFetcher, { enabled: status === "authenticated" } ); // 会话加载中时显示占位 if (status === "loading") return <div>加载中...</div>; // 请求失败处理 if (error) return <div>获取用户数据失败</div>; // 数据未就绪时返回空 if (!userData) return null; return <div>用户名:{userData.name}</div>; } export default UserProfile;
方案二:封装自定义Hook统一处理逻辑
如果多个组件都需要类似的逻辑,可以封装一个自定义Hook,整合useSession和useSWR的逻辑,减少重复代码:
import { useSession } from "next-auth/react"; import useSWR from "swr"; export function useAuthSWR(key, fetcher, options = {}) { const { data: session, status } = useSession(); // 合并SWR配置,强制会话认证后才启用请求 const swrConfig = { ...options, enabled: (options.enabled ?? true) && status === "authenticated" }; // 给fetcher注入会话信息 const authFetcher = session ? (...args) => fetcher(...args, session) : null; return useSWR( status === "authenticated" ? key : null, authFetcher, swrConfig ); } // 使用示例 function Dashboard() { const { data: dashboardData, error } = useAuthSWR( "/api/dashboard", (url, session) => fetch(url, { headers: { Authorization: `Bearer ${session.user.accessToken}` } }).then(res => res.json()) ); const { status } = useSession(); if (status === "loading") return <div>初始化中...</div>; if (error) return <div>加载仪表盘失败</div>; return <div>今日访问量:{dashboardData.views}</div>; }
方案三:在Fetcher中主动校验会话(辅助方案)
如果需要在请求层面做兜底校验,可以在fetcher中主动获取会话,若会话未就绪则抛出错误,但仍建议配合enabled选项使用,避免不必要的请求:
import { getSession } from "next-auth/react"; import useSWR from "swr"; const safeFetcher = async (url) => { const session = await getSession(); if (!session) throw new Error("会话未就绪"); const res = await fetch(url, { headers: { Authorization: `Bearer ${session.user.accessToken}` } }); return res.json(); }; function Orders() { const { status } = useSession(); const { data: orders, error } = useSWR( "/api/orders", safeFetcher, { enabled: status !== "loading" } ); if (status === "loading") return <div>加载中...</div>; if (error) return <div>获取订单失败:{error.message}</div>; return <ul>{orders.map(order => <li key={order.id}>订单{order.id}</li>)}</ul>; }
所有方案的核心都是通过Next Auth的会话状态判断,确保SWR仅在会话就绪后发起请求,避免因会话未同步导致的无效请求或权限错误。
内容的提问来源于stack exchange,提问作者RORN DEV
相关产品推荐
相关产品推荐

