NextJS 14 App Router动态路由返回404页却带200状态码,如何保留loading.tsx并修正?
Next.js 14 App Router:保留loading.tsx同时正确返回404状态码
问题原因
当路由组件被loading.tsx(即Suspense边界)包裹时,若在页面组件的顶层逻辑中调用notFound(),服务器端已经完成初始响应的状态码设置(默认200),后续的notFound()只能触发客户端导航到404页面,无法修改服务器返回的状态码。
解决方案
将notFound()的调用时机提前到数据获取阶段,让Next.js在服务器端处理数据请求时就能识别404状态,同时保留loading.tsx的加载状态提示。
步骤1:修改数据获取函数
移除getAgentBySlug中返回null的逻辑,在捕获到agent不存在的错误时直接调用notFound():
import { notFound } from 'next/navigation'; const getAgentBySlug = async ({ slug }: RequestParameters) => { try { return await Fetch<RequestResponses, RequestParameters>({ url: `agent/getAgentBySlug/${slug}`, next: { tags: [BASE_AGENT], }, }); } catch (error) { // 确认此错误是agent不存在导致的(可根据API返回的错误信息判断) notFound(); // 添加类型断言,避免TS报错 throw new Error('Agent not found'); } };
步骤2:简化页面组件逻辑
页面组件无需再判断agent是否为null,直接使用获取到的数据即可:
export default async function AgentPage({ params: { slug } }: AgentPageProps) { const agent = await getAgentBySlug({ slug }); return ( // 页面渲染内容 ); }
补充:若API返回404但未抛出错误
如果你的Fetch工具函数不会在响应状态为404时自动抛出错误,需要手动检查响应状态并触发notFound():
// 假设Fetch函数返回原始响应对象,需自行解析 const getAgentBySlug = async ({ slug }: RequestParameters) => { const response = await fetch(`/api/agent/getAgentBySlug/${slug}`, { next: { tags: [BASE_AGENT] } }); if (!response.ok) { if (response.status === 404) { notFound(); } // 处理其他错误 throw new Error('Failed to fetch agent'); } return await response.json(); };
这样调整后,当agent不存在时,数据获取阶段会立即触发notFound(),Next.js服务器会正确返回404状态码,同时loading.tsx会正常显示直到数据请求完成(或错误触发),兼顾了用户体验和状态码正确性。
内容的提问来源于stack exchange,提问作者AmirManshadi
相关产品推荐
相关产品推荐

