发布时间:2026/7/30 11:12:38
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 和错误边界。

相关新闻

2026/7/30 12:12:41

MATLAB小波变换实战:信号去噪与数据压缩算法详解

1. 项目概述:从噪声中“听见”信号的艺术 在信号分析的世界里,我们常常面对一个尴尬的现实:采集到的原始信号,就像一张沾满灰尘的老照片,有用的信息总是被各种噪声所掩盖。无论是心电图中混杂的肌电干扰,还…

2026/7/30 12:12:41

Simulink三相锁相环(SRF-PLL)建模、参数整定与调试全攻略

1. 项目概述:三相锁相环在电力电子仿真中的核心地位 在电力电子和电机驱动的仿真世界里,三相锁相环(PLL)绝对是一个绕不开的核心组件。无论你是研究光伏并网逆变器、风力发电变流器,还是设计电机控制器,只要…

2026/7/30 12:12:41

计算机单片机毕设实战-基于 STM32F103 的火灾传感与联动灭火装置开发 基于单片机的双模式消防监测与设备控制系统设计(012601)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机,Java、小程序技术领域和毕业项目实战 ✌️…

2026/7/30 12:12:41

AI生成内容检测与降重技术方案解析

1. 项目背景与核心挑战 最近在学术圈和内容创作领域,AI生成内容(AIGC)的检测与降重需求急剧升温。作为一名长期关注AI技术应用的从业者,我注意到2024-2025年间各大高校和期刊对AI生成论文的审查标准越来越严格。许多研究者发现&am…

2026/7/30 12:12:41

SpringBoot+Vue协同过滤电影推荐系统实战

1. 项目概述:当电影推荐遇上协同过滤电影推荐系统早已不是新鲜事物,但如何构建一个既精准又高效的推荐引擎,依然是技术圈的热门话题。这个基于SpringBootVue的协同过滤电影推荐系统,核心目标是通过分析用户的历史评分数据&#xf…

2026/7/30 12:07:41

陷波滤波器设计:从原理到数字实现,精准滤除单频干扰

1. 从“滤除”到“精准剔除”:陷波器的核心价值在信号处理的世界里,滤波器是当之无愧的主角。我们最常接触的是低通、高通、带通这些“门卫”,它们负责让特定频率范围的信号通过,把其他频率挡在门外。但今天要聊的这位&#xff0c…

2026/7/29 22:32:30

PDF合并与动态水印的工程化方案:2026国内免费工具实测对比

一、背景与测试方案 在实际项目交付中,PDF文件合并与版权保护水印的叠加是一个高频但容易被低估的技术需求。典型的处理链路涉及:多源PDF的文件流合并、页面级水印渲染(含透明度混合与图层叠加)、输出文件体积控制。看似简单的操作…

2026/7/30 0:01:39

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:01:39

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

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

2026/7/29 13:12:43

3个高效策略:快速掌握Axure中文界面配置

3个高效策略:快速掌握Axure中文界面配置 【免费下载链接】axure-cn Chinese language file for Axure RP. Axure RP 简体中文语言包。支持 Axure 11、10、9。不定期更新。 项目地址: https://gitcode.com/gh_mirrors/ax/axure-cn 还在为Axure RP的英文界面感…