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。不过,如果你正在通用地实现路由器,那么处理缺失路由就很有意义。这会自动为每个应用完成,但你也可以自定义。
import { Unmatched } from 'expo-router';
export default Unmatched;
这将渲染默认的 Unmatched。你也可以导出任何你想要渲染的组件来替代它。我们建议提供一个指向 / 的链接,这样用户就可以返回主页。
路由优先级
在 Web 上,文件按以下顺序提供:
- public 目录中的静态文件。
- app 目录中的标准路由和动态路由。
- app 目录中的 API 路由。
- 未找到的路由最后提供,并返回 404 状态码。
错误处理
Expo Router 支持细粒度的错误处理,以便将来启用更具约束性的数据加载策略。
你可以从任意路由中导出一个嵌套的 ErrorBoundary 组件,以使用 React 错误边界 拦截并格式化组件级错误:
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 错误边界包装,效果如下:
function Route({ ErrorBoundary, Component }) {
return (
<Try catch={ErrorBoundary}>
<Component />
</Try>
);
}
当 ErrorBoundary 不存在时,错误将抛给最近的父级 ErrorBoundary,并接受 error 和 retry 属性。
布局中屏幕的错误边界
屏幕错误边界会在屏幕抛出错误时,让导航器 UI(例如标题栏和标签栏)保持挂载。可在布局或导航器上配置:
import { Stack, type ErrorBoundaryProps } from 'expo-router';
import { Text } from 'react-native';
function ScreenErrorBoundary({ error, retry }: ErrorBoundaryProps) {
return <Text onPress={retry}>Try again: {error.message}</Text>;
}
export const unstable_settings = {
screenErrorBoundary: ScreenErrorBoundary,
};
export default function Layout() {
return <Stack />;
}
或者,也可以在导航器上配置错误边界:
import { Stack, type ErrorBoundaryProps } from 'expo-router';
import { Text } from 'react-native';
function ScreenErrorBoundary({ error, retry }: ErrorBoundaryProps) {
return <Text onPress={retry}>Try again: {error.message}</Text>;
}
export default function Layout() {
return <Stack unstable_screenErrorBoundary={ScreenErrorBoundary} />;
}
Expo Router 按以下顺序应用错误边界:
- 从屏幕导出的
ErrorBoundary
- 导航器级属性(例如
Stack)
- 在 _layout.tsx 文件中声明的
unstable_settings.screenErrorBoundary
嵌套布局会继承 unstable_settings.screenErrorBoundary,除非它们定义了自己的屏幕错误边界。在嵌套布局中将 screenErrorBoundary 设为 null,即可停止继承。
正在进行的工作
React Native 的 LogBox 需要以更不激进的方式呈现,以便在存在错误时进行开发。目前,它会针对 console.error 和 console.warn 显示。但理想情况下,它只应在出现未捕获错误时显示。
使用 Suspense fallback 的加载状态
重要 自定义 suspense fallback 在 SDK 56 及更高版本中可用。
在 SDK 58 及更高版本中,异步路由默认在 web 上启用,并使用默认加载 fallback,而不是自定义的 SuspenseFallback 导出。若要在 web 上使用以下示例,请在应用配置的 expo-router config plugin 中设置 asyncRoutes: { web: false }。这会恢复同步路由加载和自定义 fallback 支持。Native 默认设置不变。
Expo Router 会将每个路由包装在 React Suspense 边界中。你可以从布局文件导出 SuspenseFallback 组件,自定义任意子路由处于挂起状态时显示的加载 UI:
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 />;
}
当多个父级布局定义了 fallback 时,最近的父级优先。
访问路由参数
SuspenseFallback 组件接收 route 和 params 属性。你可以使用 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 />;
}
限制
- 异步路由 不支持自定义的 Suspense fallback。