This documentation is available as Markdown for AI agents and LLMs. See the full Markdown index or append .md to any documentation URL.

错误处理和加载状态

编辑页面

了解在使用 Expo Router 时,如何在应用中处理未匹配的路由、错误和加载状态。


本指南说明在使用 Expo Router 时,如何处理应用中的未匹配路由、错误和加载状态。

未匹配的路由

原生应用没有服务器,因此从技术上讲并不存在 404。不过,如果你正在通用地实现一个路由器,那么处理缺失路由就很有意义。这会为每个应用自动完成,但你也可以自定义它。

src/app/+not-found.tsx
import { Unmatched } from 'expo-router'; export default Unmatched;

这将渲染默认的 Unmatched。你也可以导出任何你想要渲染的组件来替代它。我们建议提供一个指向 / 的链接,这样用户就可以返回主页。

路由优先级

在 Web 上,文件按以下顺序提供:

  1. public 目录中的静态文件。
  2. app 目录中的标准路由和动态路由。
  3. app 目录中的 API 路由
  4. 未找到路由将最后被提供,并返回 404 状态码。

错误处理

Expo Router 支持细粒度的错误处理,以便在未来启用更具约束性的数据加载策略。

你可以从任意路由中导出一个嵌套的 ErrorBoundary 组件,以便使用 React 错误边界 拦截并格式化组件级错误:

src/app/home.tsx
import { View, Text } from 'react-native'; import { type ErrorBoundaryProps } from 'expo-router'; export function ErrorBoundary({ error, retry }: ErrorBoundaryProps) { return ( <View style={{ flex: 1, backgroundColor: "red" }}> <Text>{error.message}</Text> <Text onPress={retry}>再试一次?</Text> </View> ); } export default function Page() { ... }

当你导出一个 ErrorBoundary 时,该路由将被 React 错误边界包装,效果如下:

Virtual
function Route({ ErrorBoundary, Component }) { return ( <Try catch={ErrorBoundary}> <Component /> </Try> ); }

ErrorBoundary 不存在时,错误将抛给最近的父级 ErrorBoundary,并接受 errorretry 属性。

进行中

React Native 的 LogBox 需要以更不激进的方式呈现,以便在存在错误时进行开发。目前,它会针对 console.errorconsole.warn 显示。但理想情况下,它只应在出现未捕获错误时显示。

使用 Suspense fallback 的加载状态

Expo Router 会将每个路由包裹在一个 React Suspense 边界中。你可以从布局文件中导出一个 SuspenseFallback 组件,以自定义任何子路由挂起时显示的加载界面:

src/app/_layout.tsx
import { ActivityIndicator, View } from 'react-native'; import { Stack } from 'expo-router'; export function SuspenseFallback() { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <ActivityIndicator size="large" /> </View> ); } export default function RootLayout() { return <Stack />; }

访问路由参数

SuspenseFallback 组件接收 routeparams 属性。你可以使用 params 来为动态路由显示上下文相关的加载状态,例如:

src/app/(app)/_layout.tsx
import { ActivityIndicator, Text, View } from 'react-native'; import { Stack, type SuspenseFallbackProps } from 'expo-router'; export function SuspenseFallback({ params }: SuspenseFallbackProps) { return ( <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}> <Text>正在加载个人资料 {params.id}...</Text> <ActivityIndicator size="large" /> </View> ); } export default function AppLayout() { return <Stack />; }

限制