React 第五十三节 Router中 useRouteError 的使用详解和案例分析

前言

useRouteErrorReact Router v6.4+ 引入的关键错误处理钩子,用于在 路由错误边界Error Boundary) 中获取路由操作过程中发生的错误信息。
它提供了优雅的错误处理机制,让开发者能够创建用户友好的错误界面。

一、useRouteError 核心用途

1.1、错误捕获:

获取路由加载、渲染或数据提交过程中发生的错误

1.2、错误展示:

在错误边界组件中显示有意义的错误信息

1.3、错误恢复:

提供错误恢复机制(如重试按钮)

1.4、错误分类:

根据错误类型显示不同的UI界面

二、useRouteError 基本用法示例

import { useRouteError } from 'react-router-dom';function ErrorPage() {const error = useRouteError();return (<div id="error-page"><h1>哎呀!出错了</h1><p>抱歉,发生了一个意外的错误。</p><p><i>{error.statusText || error.message}</i></p></div>);
}

三、useRouteError 实际应用场景

3.1、基本错误边界组件

import { useRouteError, isRouteErrorResponse } from 'react-router-dom';export function ErrorBoundary() {const error = useRouteError();// 检查是否为路由错误响应if (isRouteErrorResponse(error)) {return (<div className="error-container"><h1 className="error-title">{error.status} {error.statusText}</h1><p className="error-message">{error.data}</p>{error.status === 404 && (<Link to="/" className="home-link">返回首页</Link>)}</div>);}// 处理其他类型的错误return (<div className="error-container"><h1 className="error-title">未知错误</h1><p className="error-message">{error.message || '发生了一个未知错误'}</p><button className="retry-btn"onClick={() => window.location.reload()}>重试</button></div>);
}

3.2、分层错误边界

// 根错误边界 - 应用级别错误
export function RootErrorBoundary() {const error = useRouteError();return (<div className="fullscreen-error"><div className="error-card"><h1>应用错误</h1><p>抱歉,整个应用出现了问题</p><ErrorDetails error={error} /><div className="actions"><button onClick={() => window.location.reload()}>刷新应用</button><a href="/">返回首页</a></div></div></div>);
}// 路由级别错误边界
export function RouteErrorBoundary() {const error = useRouteError();return (<div className="route-error"><h2>页面错误</h2><ErrorDetails error={error} /><div className="actions"><button onClick={() => window.history.back()}>返回上一页</button></div></div>);
}// 错误详情组件
function ErrorDetails({ error }) {return (<div className="error-details"><p><strong>错误信息:</strong> {error.message}</p>{isRouteErrorResponse(error) && (<p><strong>状态码:</strong> {error.status}</p>)}{error.stack && (<details className="stack-trace"><summary>查看技术细节</summary><pre>{error.stack}</pre></details>)}</div>);
}

3.3、在路由配置中使用错误边界

import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import {RootLayout,Dashboard,UserProfile,Settings,RootErrorBoundary,RouteErrorBoundary
} from './components';const router = createBrowserRouter([{path: '/',element: <RootLayout />,errorElement: <RootErrorBoundary />, // 应用级错误边界children: [{index: true,element: <Dashboard />},{path: 'profile/:userId',element: <UserProfile />,errorElement: <RouteErrorBoundary />, // 路由级错误边界loader: userProfileLoader // 可能抛出错误的loader},{path: 'settings',element: <Settings />,errorElement: <RouteErrorBoundary />,action: settingsAction // 可能抛出错误的action}]}
]);function App() {return <RouterProvider router={router} />;
}

3.4、自定义错误类型处理

import { useRouteError } from 'react-router-dom';export function ApiErrorBoundary() {const error = useRouteError();// 处理API错误if (error.name === 'ApiError') {return (<div className="api-error"><h2>API 请求失败</h2><p>错误代码: {error.code}</p><p>{error.message}</p>{error.code === 401 ? (<button onClick={() => location.href = '/login'}>重新登录</button>) : (<button onClick={() => window.location.reload()}>重试</button>)}</div>);}// 处理路由错误响应if (isRouteErrorResponse(error)) {switch (error.status) {case 404:return <NotFoundError error={error} />;case 403:return <ForbiddenError error={error} />;case 500:return <ServerError error={error} />;default:return <GenericHttpError error={error} />;}}// 默认错误处理return <GenericError error={error} />;
}// 404错误组件
function NotFoundError({ error }) {return (<div className="not-found"><h1>页面未找到</h1><p>您访问的页面不存在</p><p>错误信息: {error.data || error.statusText}</p><Link to="/" className="home-link">返回首页</Link></div>);
}// 403错误组件
function ForbiddenError({ error }) {return (<div className="forbidden"><h1>权限不足</h1><p>您没有权限访问此内容</p><div className="actions"><button onClick={() => window.history.back()}>返回上一页</button><Link to="/contact">联系管理员</Link></div></div>);
}

3.5、结合加载器的错误处理

// 用户详情页loader
export async function userLoader({ params }) {try {const user = await fetchUser(params.userId);if (!user) {// 抛出404错误响应throw new Response('用户未找到', {status: 404,statusText: 'Not Found'});}return user;} catch (error) {// 抛出自定义API错误throw new ApiError({message: '加载用户数据失败',code: error.status || 500,originalError: error});}
}// 自定义API错误类
export class ApiError extends Error {constructor({ message, code, originalError }) {super(message);this.name = 'ApiError';this.code = code;this.originalError = originalError;// 保留原始堆栈跟踪if (originalError?.stack) {this.stack = originalError.stack;}}
}

四、useRouteError 高级用法:错误恢复机制

import { useRouteError, useNavigate } from 'react-router-dom';export function RecoverableErrorBoundary() {const error = useRouteError();const navigate = useNavigate();const [retryCount, setRetryCount] = useState(0);const handleRetry = () => {setRetryCount(c => c + 1);navigate('.'); // 重新加载当前路由};const handleBack = () => {navigate(-1); // 返回上一页};return (<div className="recoverable-error"><h1>发生错误</h1><p>{error.message || '请稍后再试'}</p><div className="error-actions"><button onClick={handleRetry} className="retry-btn">重试 {retryCount > 0 && `(${retryCount})`}</button><button onClick={handleBack} className="back-btn">返回</button></div>{retryCount > 2 && (<div className="advanced-options"><p>多次重试失败?</p><button onClick={() => window.location.reload()}>刷新整个页面</button><Link to="/support">联系支持</Link></div>)}</div>);
}

五、useRouteError 错误类型处理指南

错误类型 识别方法 推荐处理方式
404 Not Found: error.status === 404; 显示"未找到"页面,提供返回首页链接
403 Forbidden: error.status === 403; 显示权限不足信息,提供登录或联系管理员选项
500 Server Error:error.status === 500;显示服务器错误,提供重试或联系支持选项
网络错误 :error instanceof TypeError; 显示连接问题,检查网络并提供重试
自定义错误: 自定义错误类; 根据业务逻辑定制错误处理
未捕获异常: 其他所有错误; 显示通用错误信息,提供技术细节

六、useRouteError 最佳实践

6.1、分层错误边界:

应用级:捕获整个应用的意外错误

路由级:处理特定路由的错误

组件级:处理局部UI错误

6.2、用户友好信息:

避免显示技术性错误信息给普通用户

提供清晰的恢复操作指引

为开发环境保留详细错误日志

6.3、错误恢复机制:

提供重试按钮

实现返回上一页功能

添加刷新页面选项

6.4、错误日志记录:

    useEffect(() => {if (error) {logErrorToService(error);}}, [error]);

6.5、开发环境增强:

function ErrorDetails({ error }) {return (<div>{process.env.NODE_ENV === 'development' && (<details><summary>开发人员详情</summary><pre>{error.stack}</pre></details>)}</div>);
}

七、useRouteError 注意事项

7.1、错误边界位置:

错误边界必须位于路由层级中

只能捕获其子组件树中的错误

7.2、错误类型检查:

使用 isRouteErrorResponse 检查路由错误响应

处理各种可能的错误类型

7.3、异步错误处理:

loader/action 中的异步错误会被自动捕获

组件中的错误需要使用 useRouteError 获取

7.4、错误传播:

错误会向上传播到最近的错误边界

未被捕获的错误会导致应用崩溃

7.5、与React错误边界结合:

class ReactErrorBoundary extends React.Component {state = { hasError: false };static getDerivedStateFromError() {return { hasError: true };}render() {if (this.state.hasError) {return <RouterErrorBoundary />;}return this.props.children;}
}

总结

useRouteErrorReact Router v6.4+ 错误处理机制的核心,可以帮助我们实现如下场景:

  1. 创建用户友好的错误界面
  2. 实现分层错误处理策略
  3. 根据错误类型提供定制化UI
  4. 实现错误恢复和重试机制
  5. 结合路由加载器和动作进行错误处理

通过合理使用 useRouteError,我们可以显著提升应用的健壮性和用户体验,确保即使发生错误,用户也能获得清晰的反馈和恢复路径。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/diannao/85813.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[arthas]arthas安装使用

arthas是阿里开源的一个java线上监控以及诊断工具&#xff0c;在docker容器中我们无需重启服务&#xff0c;也不用更改代码&#xff0c;就可以完成对应用内存、线程、日志级别的修改、方法调用的出入参、异常监测、执行耗时等&#xff0c;xxxx.xxxx.xxxxx为脱敏内容 1. 在docke…

Flask-Babel 使用示例

下面创建一个简单的 Flask-Babel 示例&#xff0c;展示如何在 Flask 应用中实现国际化和本地化功能。这个示例将包括多语言支持&#xff08;中文和英文&#xff09;、语言切换功能以及翻译文本的使用。 项目结构 我们将创建以下文件结构&#xff1a; 1. 首先&#xff0c;创…

[论文阅读] 软件工程 | 量子计算如何赋能软件工程(Quantum-Based Software Engineering)

arXiv:2505.23674 [pdf, html, other] Quantum-Based Software Engineering Jianjun Zhao Subjects: Software Engineering (cs.SE); Quantum Physics (quant-ph) 量子计算如何赋能软件工程 我们在开发软件时&#xff0c;常常会遇到一些棘手的问题。比如&#xff0c;为了确保软…

Ansible 进阶 - Roles 与 Inventory 的高效组织

Ansible 进阶 - Roles 与 Inventory 的高效组织 如果说 Playbook 是一份完整的“菜谱”,那么 Role (角色) 就可以被看作是制作这道菜(或一桌菜)所需的标准化“备料包”或“半成品组件”。例如,我们可以有一个“Nginx Web 服务器安装配置 Role”、“MySQL 数据库基础设置 Ro…

青少年编程与数学 01-011 系统软件简介 04 Linux操作系统

青少年编程与数学 01-011 系统软件简介 04 Linux操作系统 一、Linux 的发展历程&#xff08;一&#xff09;起源&#xff08;二&#xff09;早期发展&#xff08;三&#xff09;成熟与普及&#xff08;四&#xff09;移动与嵌入式领域的拓展 二、Linux 的内核与架构&#xff08…

将图形可视化工具的 Python 脚本打包为 Windows 应用程序

前文我们已经写了一个基于python的tkinter库和matplotlib库的图形可视化工具。 基于Python的tkinter库的图形可视化工具&#xff08;15种图形的完整代码&#xff09;:基于Python的tkinter库的图形可视化工具&#xff08;15种图形的完整代码&#xff09;-CSDN博客 在前文基础上&…

【Kotlin】简介变量类接口

【Kotlin】简介&变量&类&接口 【Kotlin】数字&字符串&数组&集合 【Kotlin】高阶函数&Lambda&内联函数 【Kotlin】表达式&关键字 文章目录 Kotlin_简介&变量&类&接口Kotlin的特性Kotlin优势创建Kotlin项目变量变量保存了指向对…

OpenCV种的cv::Mat与Qt种的QImage类型相互转换

一、首先了解cv::Mat结构体 cv::Mat::step与QImage转换有着较大的关系。 step的几个类别区分: step:矩阵第一行元素的字节数step[0]:矩阵第一行元素的字节数step[1]:矩阵中一个元素的字节数step1(0):矩阵中一行有几个通道数step1(1):一个元素有几个通道数(channel()) cv::Ma…

搭建基于VsCode的ESP32的开发环境教程

一、VsCode搜索ESP-IDF插件 根据插件处搜索找到ESP-IDF并安装 安装完成 二、配置安装ESP-IDF 配置IDF 按照如下配置&#xff0c;点击安装 安装完成 三、使用案例程序 创建一个闪光灯的例子程序&#xff0c;演示程序编译下载。 选择blink例子&#xff0c;闪烁LED的程序 选…

企业培训学习考试系统源码 ThinkPHP框架+Uniapp支持多终端适配部署

在数字化转型浪潮下&#xff0c;企业对高效培训与精准考核的需求日益迫切。一套功能完备、多终端适配且易于定制的培训学习考试系统&#xff0c;成为企业提升员工能力、检验培训成果的关键工具。本文给大家分享一款基于 ThinkPHP 框架与 Uniapp 开发的企业培训学习考试系统&…

【PmHub面试篇】PmHub集成Redission分布式锁保障流程状态更新面试专题解析

你好&#xff0c;欢迎来到本次关于PmHub整合TransmittableThreadLocal (TTL)缓存用户数据的面试系列分享。在这篇文章中&#xff0c;我们将深入探讨这一技术领域的相关面试题预测。若想对相关内容有更透彻的理解&#xff0c;强烈推荐参考之前发布的博文&#xff1a;【PmHub后端…

mac 设置cursor (像PyCharm一样展示效果)

一、注册 Cursor - The AI Code Editor 二、配置Python环境 我之前使用pycharm创建的python项目&#xff0c;以及创建了虚拟环境&#xff0c;现在要使用cursor继续开发。 2.1 选择Python 虚拟环境 PyCharm 通常将虚拟环境存储在项目目录下的 venv 或 .venv 文件夹中&#xf…

Spring事务失效-----十大常见场景及解决方案全解析

Spring事务失效的常见场景及原因分析 Spring事务管理是开发中的核心功能,但在实际应用中可能因各种原因导致事务失效。以下是常见的事务失效场景及详细解析: 1. 方法未被Spring管理 场景:使用new关键字直接创建对象,而非通过Spring容器注入原因:Spring事务基于AOP代理,…

刚出炉热乎的。UniApp X 封装 uni.request

HBuilder X v4.66 当前最新版本 由于 uniapp x 使用的是自己包装的 ts 语言 uts。目前语言还没有稳定下来&#xff0c;各种不支持 ts 各种报错各种不兼容问题。我一个个问题调通的&#xff0c;代码如下&#xff1a; 封装方法 // my-app/utils/request.uts const UNI_APP_BASE…

【ArcGIS微课1000例】0148:Geographic Imager6.2使用教程

文章目录 一、Geographic Imager6.2下载安装二、Geographic Imager6.2使用方法1. 打开Geographic Imager2. 导入地理影像3. 导入DEM地形渲染4. 设置地理坐标系统5. 进行地理影像的处理6. 导出地理影像一、Geographic Imager6.2下载安装 在专栏上一篇文章中已经详细讲述了Geogr…

零基础安装 Python 教程:从下载到环境配置一步到位(支持 VSCode 和 PyCharm)与常用操作系统操作指南

零基础安装 Python 教程&#xff1a;从下载到环境配置一步到位&#xff08;支持 VSCode 和 PyCharm&#xff09;与常用操作系统操作指南 本文是一篇超详细“Python安装教程”&#xff0c;覆盖Windows、macOS、Linux三大操作系统的Python安装方法与环境配置&#xff0c;包括Pyt…

定时任务的 cron 表达式

定时任务的 cron 表达式 一、什么时 cron 表达式 Cron表达式是一种广泛应用于Linux系统的时间表示格式&#xff0c;常用于定时任务的调度。Cron表达式可以通过指定不同的时间参数&#xff0c;描述一个在 未来某个时间点执行的任务。 二、Cron表达式语法 秒 分 时 日 月 周几…

PHP+mysql 美容美发预约小程序源码 支持DIY装修+完整图文搭建教程

在数字化浪潮席卷的当下&#xff0c;美容美发行业也急需线上转型&#xff0c;以提升客户预约效率与服务体验。开发一款美容美发预约小程序成为众多商家的迫切需求。本文将为大家分享一套基于 PHPMySQL 的美容美发预约小程序源码&#xff0c;功能完备、支持 DIY 装修&#xff0c…

十八、【用户认证篇】安全第一步:基于 JWT 的前后端分离认证方案

【用户认证篇】安全第一步:基于 JWT 的前后端分离认证方案 前言什么是 JWT (JSON Web Token)?准备工作第一部分:后端 Django 配置 JWT 认证1. 安装 `djangorestframework-simplejwt`2. 在 `settings.py` 中配置 `djangorestframework-simplejwt`3. 在项目的 `urls.py` 中添加…

03 Deep learning神经网络的编程基础 代价函数(Cost function)--吴恩达

深度学习中的损失函数(Cost Function)用于量化模型预测与真实数据的差距,是优化神经网络的核心指标。以下是常见类型及数学表达: 核心原理 逻辑回归通过sigmoid函数将线性预测结果转换为概率: y ^ ( i ) \hat{y}^{(i)}