Next.js服务器端数据获取异常:加载状态异常问题排查
问题根源及修复方案
核心问题
- 全局变量滥用:
statsData是组件外的全局变量,React 无法追踪其变化,数据获取完成后组件不会自动重新渲染,导致首次加载一直显示 Loading。同时服务端全局变量会在请求间共享,引发数据泄露或竞态问题。 - 未正确使用异步服务端组件:Next.js 服务端组件支持异步写法,但你的
Dashboard组件未标记为async,无法等待数据获取完成再渲染,直接返回了 Loading 状态。 - 错误处理缺失:未捕获数据获取过程中的异常(如 Cookie 不存在的情况),也未正确处理请求失败的场景。
- 缓存配置不明确:默认情况下 Next.js 会缓存
fetch请求,可能导致 stale 数据,不过这不是你当前问题的主要原因。
修复后的代码
1. Dashboard 组件(改为异步服务端组件)
async function getData() { const res = await fetchDataServerSide('stats'); if (!res.ok) { throw new Error('Failed to fetch data'); } return res.json(); } const Dashboard = async () => { try { const statsData = await getData(); return ( <div className="p-6"> <div className="pb-6"> <Stats stats={statsData} /> </div> </div> ); } catch (error) { return <div>Failed to load</div>; } }; export default Dashboard;
2. fetchDataServerSide 函数(增加 Cookie 校验及缓存控制)
async function fetchDataServerSide(url: string): Promise<Response> { 'use server'; const fetch_path = `${process.env.NEXT_PUBLIC_BACKEND_URL}/api/${url}`; // 校验 Cookie 是否存在,避免 runtime 错误 const xsrfToken = cookies().get('XSRF-TOKEN'); const laravelSession = cookies().get('laravel_session'); if (!xsrfToken || !laravelSession) { throw new Error('Authentication cookies are missing'); } const options: RequestInit = { method: "GET", headers: { "Accept": "application/json", "Referer": process.env.APP_URL || '', "X-Requested-With": "XMLHttpRequest", "Content-Type": "application/json", "cookie": `XSRF-TOKEN=${xsrfToken.value}; laravel_session=${laravelSession.value}`, }, // 禁用缓存(按需调整:若需缓存可改为 revalidate: 60 表示 60 秒刷新一次) cache: 'no-store', }; return await fetch(fetch_path, options); }
关键修复点说明
- 移除全局变量:将数据获取结果直接返回并在组件内 await,避免全局变量导致的状态不一致和数据泄露。
- 异步服务端组件:标记
Dashboard为async,等待数据获取完成后再渲染页面内容,首次加载时服务端会等待数据就绪后再返回完整 HTML,不会显示 Loading。 - 完善错误处理:添加
try/catch捕获数据获取异常,同时校验 Cookie 存在性,避免未授权请求或 runtime 错误。 - 明确缓存策略:通过
cache: 'no-store'禁用缓存,确保每次请求都获取最新数据;若允许缓存,可使用revalidate参数设置缓存有效期。
内容的提问来源于stack exchange,提问作者user101289
相关产品推荐
相关产品推荐

