Expo Router应用启动时如何根据用户角色重定向至对应目录
问题解决:Expo路由启动时根据用户角色定向到对应目录
问题根源
Expo Router启动时,若未明确控制初始路由,会默认加载同层级下字母排序靠前的路由目录(如business_auth)。当前配置仅在未登录时重定向到登录页,但已登录用户启动应用时,会话状态读取滞后于路由初始化,导致先加载了字母排序靠前的目录。
解决方案
通过在auth/_layout.tsx中添加基于角色的路由重定向逻辑,结合会话加载状态控制,避免启动时的错误跳转。核心是在会话状态就绪后,根据用户角色定向到对应目录,同时阻止初始路由的默认渲染。
修改后的auth/_layout.tsx代码
import * as SplashScreen from "expo-splash-screen"; import { SessionProvider, useSession } from "@/services/ctx"; import { ErrorBoundary, Slot, useRouter } from "expo-router"; import { useEffect, useState } from "react"; export { ErrorBoundary } from "expo-router"; export const unstable_settings = { initialRouteName: "login", }; // 保持启动页直到重定向完成 SplashScreen.preventAutoHideAsync(); export default function RootLayout() { return ( <SessionProvider> {/* 新增重定向处理组件,在SessionProvider内部可读取会话状态 */} <RoleBasedRedirect /> <Slot /> </SessionProvider> ); } function RoleBasedRedirect() { const router = useRouter(); const { session, isLoading } = useSession(); // 假设useSession返回:会话信息(含role)、加载状态 const [redirectDone, setRedirectDone] = useState(false); useEffect(() => { const handleRedirect = async () => { if (!isLoading) { if (session) { // 根据角色匹配目标路由 const targetRoute = session.role === "staff" ? "/auth/staff_auth" : "/auth/business_auth"; // 避免重复重定向循环 const currentRoute = router.getCurrentRoute()?.name; if (currentRoute !== targetRoute.split("/").pop()) { router.replace(targetRoute); } } else { // 未登录时跳转登录页 router.replace("/auth/login"); } // 重定向完成后隐藏启动页 await SplashScreen.hideAsync(); setRedirectDone(true); } }; handleRedirect(); }, [session, isLoading, router]); // 重定向完成前不渲染任何内容,防止闪现错误页面 if (!redirectDone) { return null; } return null; }
关键注意事项
- 会话状态需包含加载状态:确保
SessionProvider在从本地存储(如AsyncStorage)读取会话时,返回isLoading状态,避免在会话未就绪时执行重定向。 - 使用
router.replace:替代push,避免留下历史记录,确保用户无法通过返回按钮回到登录页(除非主动退出)。 - 阻止初始路由渲染:重定向完成前返回
null,避免启动时闪现business_auth页面。 - 启动页控制:保持
SplashScreen直到重定向完成,提升用户体验。
内容的提问来源于stack exchange,提问作者Alicia
相关产品推荐
相关产品推荐

