如何等待Expo Router就绪后再执行路由操作?
解决Expo Router v2中“导航在根布局挂载前执行”的错误
你遇到的错误是因为在index.js的组件渲染阶段直接调用router.replace,此时根布局的导航器还未完成挂载,导致路由操作无法正常执行。以下是两种有效解决方案:
方案一:在index.js中使用useEffect延迟导航
将路由跳转逻辑放到useEffect钩子中,确保组件挂载后(此时导航器已就绪)再执行导航操作:
修改后的index.js代码:
import { Text, View, useEffect } from 'react-native'; import { Link, router} from 'expo-router'; export default function App(){ const isLoggedIn = false; // 替换为实际登录状态判断逻辑 useEffect(() => { // 组件挂载后执行导航 isLoggedIn ? router.replace("/home") : router.replace("/welcome"); }, [isLoggedIn]); return ( <View> <Text>Sorry, an error has occured, this page should not be visible</Text> <Text>Current file: index.js</Text> <Link href="/home">Go to default page</Link> </View> ) }
方案二:在RootLayout中处理重定向(推荐)
把路由重定向逻辑移到根布局_layout.js中,更符合Expo Router的架构设计,避免中间页index.js的冗余:
修改后的_layout.js代码:
import { useFonts } from 'expo-font'; import { SplashScreen, Stack, useRouter } from 'expo-router'; import { useEffect } from 'react'; import { useColorScheme } from 'react-native'; export { ErrorBoundary, } from 'expo-router'; export const unstable_settings = { initialRouteName: 'index', }; SplashScreen.preventAutoHideAsync(); export default function RootLayout() { const colorScheme = useColorScheme(); const router = useRouter(); // 替换为实际的登录状态获取逻辑,比如从AsyncStorage/Context读取 const isLoggedIn = false; const [loaded, error] = useFonts({ }); useEffect(() => { if (error) throw error; }, [error]); useEffect(() => { if (loaded) { SplashScreen.hideAsync(); // 字体加载完成后执行导航 isLoggedIn ? router.replace("/home") : router.replace("/welcome"); } }, [loaded, isLoggedIn]); if (!loaded) { return null; } return ( <Stack screenOptions={{ headerShown: false }}> <Stack.Screen name="home" options={{}} /> <Stack.Screen name="welcome" options={{}} /> </Stack> ); }
额外说明
- 如果登录状态是异步获取的(比如从AsyncStorage读取),需要在
useEffect中用async/await处理,确保获取到状态后再执行导航:useEffect(() => { async function checkAuth() { const storedLoginStatus = await AsyncStorage.getItem('isLoggedIn'); const isLoggedIn = storedLoginStatus === 'true'; isLoggedIn ? router.replace("/home") : router.replace("/welcome"); } if (loaded) { SplashScreen.hideAsync(); checkAuth(); } }, [loaded]); - 使用方案二时可以直接删除
index.js文件,因为根布局会直接处理重定向逻辑。
内容的提问来源于stack exchange,提问作者10xNerd
相关产品推荐
相关产品推荐

