受保护的路由
编辑页面
了解如何使屏幕无法通过客户端导航访问。
For the complete documentation index, see llms.txt. Use this Use this file to discover all available pages.

在 Expo Router 中使用受保护路由,根据身份验证状态限制屏幕访问。
概览
受保护屏幕允许你通过客户端导航防止用户访问某些路由。如果用户尝试导航到受保护屏幕,或者某个屏幕在处于活动状态时变为受保护状态,他们将被重定向到锚点路由(通常是 index 屏幕)或堆栈中的第一个可用屏幕。
srcapp_layout.tsxindex.tsxabout.tsxlogin.tsx仅在未认证时可用private_layout.tsx仅在已认证时可用index.tsxpage.tsximport { Stack } from 'expo-router'; const isLoggedIn = false; export function AppLayout() { return ( <Stack> <Stack.Protected guard={!isLoggedIn}> <Stack.Screen name="login" /> </Stack.Protected> <Stack.Protected guard={isLoggedIn}> <Stack.Screen name="private" /> </Stack.Protected> {/* Expo Router 默认包含所有路由。添加 Stack.Protected 会为这些屏幕创建例外。 */} </Stack> ); }
在这个示例中,/private 路由无法访问,因为 guard 为 false。当用户尝试访问 /private 时,他们会被重定向到锚点路由,也就是 index 屏幕。
此外,如果用户当前位于 /private/page,并且 guard 条件变为 false,他们也会自动被重定向。
当某个屏幕的 guard 从 true 改为 false 时,它的所有历史记录条目都会从导航历史中移除。
多个受保护屏幕
在 Expo Router 中,一个屏幕在同一时间只能存在于一个活动路由组中。
你应该只在最合适的组或堆栈中声明一次屏幕。如果某个屏幕的可用性取决于逻辑,请将其包裹在条件组中,而不是重复声明该屏幕。
import { Stack } from 'expo-router'; const isLoggedIn = true; const isAdmin = true; export function AppLayout() { return ( <Stack> <Stack.Protected guard={true}> <Stack.Screen name="profile" /> </Stack.Protected> <Stack.Screen name="profile" /> // ❌ 不允许:重复的屏幕 </Stack> ); }
嵌套受保护屏幕
受保护屏幕可以嵌套,以定义分层访问控制逻辑。
import { Stack } from 'expo-router'; const isLoggedIn = true; const isAdmin = true; export function AppLayout() { return ( <Stack> <Stack.Protected guard={isLoggedIn}> <Stack.Protected guard={isAdmin}> <Stack.Screen name="private" /> </Stack.Protected> <Stack.Screen name="about" /> </Stack.Protected> </Stack> ); }
在这种情况下:
- 仅当用户已登录且是管理员时,
/private才受保护。 /about对任何已登录用户受保护。
回退到特定屏幕
你可以配置导航器在访问被拒绝时回退到某个特定屏幕。
srcapp_layout.tsxindex.tsxabout.tsxlogin.tsxprivate_layout.tsxindex.tsxpage.tsximport { Stack } from 'expo-router'; const isLoggedIn = false; export function AppLayout() { return ( <Stack> <Stack.Protected guard={isLoggedIn}> <Stack.Screen name="index" /> <Stack.Screen name="private" /> </Stack.Protected> <Stack.Screen name="login" /> </Stack> ); }
在上面的示例中,由于 index 屏幕受保护且 guard 为 false,路由器会重定向到第一个可用屏幕 —— login。
Tabs 和 Drawer
import { Tabs } from 'expo-router'; const isLoggedIn = false; export default function TabLayout() { return ( <Tabs> <Tabs.Screen name="index" options={{ tabBarLabel: 'Home' }} /> <Tabs.Protected guard={isLoggedIn}> <Tabs.Screen name="private" options={{ tabBarLabel: 'Private' }} /> <Tabs.Screen name="profile" options={{ tabBarLabel: 'Profile' }} /> </Tabs.Protected> <Tabs.Protected guard={!isLoggedIn}> <Tabs.Screen name="login" options={{ tabBarLabel: 'Login' }} /> </Tabs.Protected> </Tabs> ); }
自定义导航器
Protected 也可用于使用 withLayoutContext 钩子的自定义导航器。
静态渲染注意事项
受保护屏幕仅在客户端进行评估。在静态站点生成期间,不会为受保护路由创建任何 HTML 文件。不过,如果用户知道这些路由的 URL,他们仍然可以直接请求对应的 HTML 或 JavaScript 文件。受保护屏幕不能替代服务器端身份验证或访问控制。