Next.js App Router 约定式文件实战:loading、error、not-found 怎么兜住加载态与异常
Next.js App Router 约定式文件实战:loading、error、not-found 怎么兜住加载态与异常用 Next.js App Router 写页面,你迟早会遇到这三个问题:页面里await fetch(...)拉数据时,用户盯着一片空白,不知道是在加载还是卡死了。接口挂了或抛异常,整个页面直接白屏崩掉,还可能把错误堆栈暴露给用户。用户访问了一个不存在的资源(比如/posts/99999),你想给个像样的 404 页,而不是默认那个丑页面。很多人第一反应是在组件里手写isLoading、try/catch、if (!data) return NotFound/。但 App Router 提供了约定式文件——在路由目录里放特定文件名,框架自动帮你接管加载态、错误态和 404。这篇把loading.tsx、error.tsx、not-found.tsx三个一次讲透。朴素写法:所有状态挤在一个组件里先看不用约定式文件时,一个详情页大概长这样:// app/posts/[id]/page.tsx —— 反面教材 use client; import { useEffect, useState } from react; export default function PostPage({ params }: { params: { id: string } }) { const [post, setPost] useState(null); const [loading, setLoading] useState(true); const [error, setError] useState(null); useEffect(() { fetch(/api/posts/${params.id}) .then(r { if (!r.ok) throw new Error(加载失败); return r.json(); }) .then(setPost) .catch(setError) .finally(() setLoading(false)); }, [params.id]); if (loading) return p加载中.../p; if (error) return p出错了/p; if (!post) return p找不到文章/p; return articleh1{post.title}/h1p{post.body}/p/article; }问题很明显:业务渲染只有最后一行,前面全是状态判断的噪音;而且被迫写成客户端组件(use client),丢掉了服务端组件直接await数据的能力。App Router 的约定式文件就是来拆掉这些样板的。loading.tsx:自动加载态,基于 Suspense在路由目录放一个loading.tsx,Next.js 会自动用它包一层 Suspense。当同级page.tsx(服务端组件)在await数据时,先渲染loading.tsx的内容,数据好了再换成真实页面:// app/posts/[id]/loading.tsx export default function Loading() { // 骨架屏,比加载中...体验好得多 return ( div classNameanimate-pulse space-y-4 div classNameh-8 w-2/3 bg-gray-200 rounded / div classNameh-4 w-full bg-gray-200 rounded / div classNameh-4 w-5/6 bg-gray-200 rounded / /div ); }有了它,page.tsx就能回归纯粹的服务端组件,直接await,不用管 loading:// app/posts/[id]/page.tsx —— 服务端组件,直接 await export default async function PostPage({ params, }: { params: Promise{ id: string }; }) { const { id } await params; // Next.js 15 起 params 是 Promise const res await fetch(https://api.example.com/posts/${id}); const post await res.json(); return ( article h1{post.title}/h1 p{post.body}/p /article ); }关键理解:loading.tsx的本质就是给page.tsx套了Suspense fallback{Loading/}。所以它对「路由跳转时的加载」和「组件 await 期间」都生效,你什么都不用手写。error.tsx:兜住渲染异常,必须是客户端组件如果page.tsx里的 fetch 抛了异常,或者渲染过程报错,同级的error.tsx会接住它,展示降级 UI,而不是整页白屏:// app/posts/[id]/error.tsx use client; // ← error.tsx 必须是客户端组件,这是硬性要求 import { useEffect } from react; export default function Error({ error, reset, }: { error: Error { digest?: string }; reset: () void; // 调它会重新渲染这段路由,相当于重试 }) { useEffect(() { // 上报到监控系统,别把错误吞了 console.error(页面渲染出错:, error); }, [error]); return ( div classNamep-6 text-center h2 出了点问题/h2 p classNametext-gray-500{error.message}/p button onClick{() reset()} classNamemt-4 px-4 py-2 bg-blue-600 text-white rounded 重试 /button /div ); }有两个坑要记牢:坑一:error.tsx必须加use client。它内部用 React 错误边界实现,错误边界只能是客户端组件。忘了加,构建直接报错。坑二:error.tsx抓不到同级layout.tsx的错误。因为 error 边界包在 layout 内部,layout 本身抛错它管不着。要兜住 layout 的错误,得在上一级目录放error.tsx,或者用global-error.tsx兜住根 layout。reset()函数是 App Router 特有的:调用它会尝试重新渲染出错的这段路由子树,给用户一个「重试」而不用刷新整页。not-found.tsx notFound():优雅的 404资源不存在时,别手动return div404/div。App Router 提供了notFound()函数,调用它会立即中断渲染,并渲染最近的not-found.tsx:// app/posts/[id]/page.tsx import { notFound } from next/navigation; export default async function PostPage({ params, }: { params: Promise{ id: string }; }) { const { id } await params; const res await fetch(https://api.example.com/posts/${id}); if (res.status 404) { notFound(); // ← 中断渲染,跳到 not-found.tsx,后面代码不会执行 } const post await res.json(); return articleh1{post.title}/h1p{post.body}/p/article; }// app/posts/[id]/not-found.tsx import Link from next/link; export default function NotFound() { return ( div classNamep-6 text-center h2文章不存在/h2 p classNametext-gray-500你要找的文章可能已被删除。/p Link href/posts classNametext-blue-600 underline 返回文章列表 /Link /div ); }notFound()的原理是抛出一个特殊错误,被框架捕获后渲染not-found.tsx,同时响应状态码正确返回 404——这点对 SEO 很重要,搜索引擎知道这是不存在的页面,不会收录。手写div404/div的话状态码还是 200,搜索引擎会以为是正常页。它们的嵌套关系:一张图理清这几个约定式文件不是平级的,它们的包裹顺序是固定的。同一个路由段里,Next.js 大致这样嵌套:layout error ← 兜住下面的渲染错误 suspense fallback{loading} ← loading 兜住加载态 not-found 边界 page ← 你的实际页面 /not-found /suspense /error /layout从这张图能推出几条实用结论:loading和error都定义在路由段上,子路由可以有自己的一套,就近生效。error在layout内层,所以管不到同级 layout 的错误(要放上一级)。not-found既能被notFound()主动触发,也会兜住未匹配的路由。小结App Router 的三个约定式文件,把过去挤在组件里的状态处理拆成了框架职责:loading.tsx:自动 Suspense fallback,让page.tsx回归纯服务端组件直接await,写骨架屏体验最佳。error.tsx:错误边界,必须use client;提供reset()做重试;抓不到同级 layout 的错误,要放上一级。not-found.tsxnotFound():优雅 404,且返回正确的 404 状态码,对 SEO 友好;notFound()会中断后续渲染。记忆点:别再手写isLoading / try-catch / 404 判断——在路由目录里放对文件名,框架自动帮你套好 Suspense 和错误边界。

相关新闻

配电网最优潮流求解:二阶锥松弛技术与Matlab实现

配电网最优潮流求解:二阶锥松弛技术与Matlab实现

1. 项目概述:配电网最优潮流与二阶锥松弛技术配电网最优潮流(Optimal Power Flow, OPF)是电力系统运行与规划中的核心计算问题。传统OPF求解面临非凸非线性带来的计算复杂度挑战,而二阶锥松弛(Second-Order Cone Relax…

2026/7/30 11:11:29 阅读更多 →
GD32 EXMC驱动LCD:从硬件配置到GUI集成的嵌入式显示系统开发

GD32 EXMC驱动LCD:从硬件配置到GUI集成的嵌入式显示系统开发

1. 从“点灯”到“刷屏”:为什么需要EXMC来驱动LCD? 如果你玩过GD32F303这类Cortex-M4内核的MCU,点亮一个LED或者驱动一个简单的1602字符液晶,大概率是直接用GPIO模拟时序或者用SPI、I2C这类串行接口。这在小尺寸、低分辨率的屏幕…

2026/7/30 11:11:29 阅读更多 →
Kafka如何保证「消息不丢失」,「顺序传输」,「不重复消费」,以及为什么会发生重平衡(reblanace)

Kafka如何保证「消息不丢失」,「顺序传输」,「不重复消费」,以及为什么会发生重平衡(reblanace)

Kafka 如何保证「消息不丢失」「顺序传输」「不重复消费」,以及重平衡(Rebalance)原理详解 Kafka 作为分布式消息队列的标杆,在金融、电商、日志采集等场景中被广泛使用。但在生产环境中,我们经常会遇到三个核心问题&a…

2026/7/30 11:11:29 阅读更多 →

最新新闻

面试还不会Spring全家桶,看这篇就够了!

面试还不会Spring全家桶,看这篇就够了!

Spring是我们Java程序员面试和工作都绕不开的重难点。很多粉丝就经常跟我反馈说由Spring衍生出来的一系列框架太多了,根本不知道从何下手;大家学习过程中大都不成体系,但面试的时候都上升到源码级别了,你不光要清楚了解Spring源码…

2026/7/30 11:22:33 阅读更多 →
为什么92%的AI批处理脚本无法上线?资深SRE披露4大致命缺陷+可落地的6层人工审核清单(含Checklist下载链接)

为什么92%的AI批处理脚本无法上线?资深SRE披露4大致命缺陷+可落地的6层人工审核清单(含Checklist下载链接)

更多请点击: https://intelliparadigm.com 第一章:AI 写批处理脚本 在 Windows 环境下,批处理(.bat)脚本仍广泛用于自动化部署、日志清理、环境检测等轻量级运维任务。借助大语言模型(LLM)&…

2026/7/30 11:22:33 阅读更多 →
KMS智能激活方案:开源工具的完整实战指南

KMS智能激活方案:开源工具的完整实战指南

KMS智能激活方案:开源工具的完整实战指南 【免费下载链接】KMS_VL_ALL_AIO Smart Activation Script 项目地址: https://gitcode.com/gh_mirrors/km/KMS_VL_ALL_AIO KMS_VL_ALL_AIO是一款高效的开源智能激活脚本,能够为Windows系统和Office办公套…

2026/7/30 11:22:33 阅读更多 →
豆包    LeetCode 3782. 交替删除操作后最后剩下的整数 TypeScript实现

豆包 LeetCode 3782. 交替删除操作后最后剩下的整数 TypeScript实现

TypeScript / JavaScript 实现 LeetCode 3782 lastInteger题意回顾初始数组 [1,2,3,...,n] ,交替执行删除:1. 第一轮:从左删,隔一删一(保留奇数位置) 2. 第二轮:从右删,隔一删一 循…

2026/7/30 11:22:33 阅读更多 →
马斯克派船回收 Starship S40:这不是捞残骸,而是星舰复用的第一次硬件复盘

马斯克派船回收 Starship S40:这不是捞残骸,而是星舰复用的第一次硬件复盘

马斯克说正在派船回收 Starship S40,这事最有意思的地方,不是 SpaceX 又做了一次海上打捞,而是 Starship 第一次把“再入后的真实硬件”完整留给了工程团队。 如果只看飞行结果,S40 仍然是一次海上软溅落;但如果看复用…

2026/7/30 11:22:33 阅读更多 →
WAF+DDoS 双层防护架构!解决应用层混合攻击漏杀误杀问题

WAF+DDoS 双层防护架构!解决应用层混合攻击漏杀误杀问题

很多企业同时被四层流量攻击 七层 CC 攻击混合打击,单靠高防只能防流量、防不住 CC,单靠 WAF 防不住大流量。本篇详解企业标准「DDoS 高防 WAF」双层防护架构,解决漏杀、误杀、业务卡顿难题。一、双层防护分工逻辑外层 DDoS 高防&#xff1…

2026/7/30 11:21:33 阅读更多 →

日新闻

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:13 阅读更多 →
如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南

如何3步掌握Video Download Helper:网页视频下载的完整实战指南 【免费下载链接】VideoDownloadHelper Chrome Extension to Help Download Video for Some Video Sites. 项目地址: https://gitcode.com/gh_mirrors/vi/VideoDownloadHelper 你是否曾经在浏览…

2026/7/30 0:00:13 阅读更多 →
“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

“双减”后首个AI备课压力测试报告:覆盖32所中小学的176节AI辅助课,暴露4大隐性增负节点

更多请点击: https://intelliparadigm.com 第一章:AI 教师备课辅助 AI 教师备课辅助系统正逐步成为教育数字化转型的核心支撑工具,它并非替代教师,而是通过语义理解、知识图谱与多模态生成能力,将教师从重复性劳动中解…

2026/7/30 0:00:13 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/29 22:18:20 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/29 15:00:03 阅读更多 →

月新闻