Expo Router中Stack组件无法正确识别,始终显示(auth)栈而非预期的(tabs)栈
我明白你现在的困扰——明明在Stacks.tsx里用了三元表达式切换渲染(tabs)或(auth)的Stack.Screen,但不管条件是true还是false,始终只会加载(auth)栈的内容,甚至头部的显示状态都和(auth)绑定,完全看不到(tabs)栈的影子。不过你已经确认过三元表达式本身是正常的(换成普通文本能正确切换),文件结构也没问题,那问题大概率出在Expo Router对Stack.Screen的注册逻辑上。
问题根源
Expo Router的Stack组件不会根据条件渲染来动态启用/禁用路由,它会把所有被声明过的Stack.Screen都注册为可用路由。你现在把两个Stack.Screen放在同一个Stack里用三元切换,本质上Expo Router还是会同时感知到这两个路由的存在,再加上路由匹配的优先级问题,就只会优先加载(auth)栈的内容了。
解决方案
我们需要调整渲染逻辑,根据条件渲染不同的Stack结构,而不是在同一个Stack里切换Stack.Screen。修改你的Stacks.tsx如下:
// Stacks.tsx import { Stack } from 'expo-router'; export default function Stacks() { // 替换成你实际的认证/状态判断条件 const shouldShowTabs = true; if (shouldShowTabs) { return ( <Stack> <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> <Stack.Screen name="+not-found" /> </Stack> ); } else { return ( <Stack> <Stack.Screen name="(auth)" options={{ headerShown: false }} /> <Stack.Screen name="+not-found" /> </Stack> ); } }
补充说明
这种写法的核心是:让Expo Router在不同条件下只注册对应需要的路由组。当shouldShowTabs为true时,Stack里只包含(tabs)的路由注册,此时Expo Router会优先匹配(tabs)下的页面;当条件为false时,只注册(auth)路由,就会自动跳转到(auth)的登录页面。
另外再确认一下你其他文件的写法是没问题的,以下是格式化后的代码参考:
(tabs)/_layout.tsx
// (tabs)/_layout.tsx export default function TabLayout() { const colorScheme = useColorScheme(); return ( <Tabs screenOptions={{ tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint, headerShown: false, tabBarButton: HapticTab, tabBarBackground: TabBarBackground, tabBarStyle: Platform.select({ ios: { // Use a transparent background on iOS to show the blur effect position: 'absolute', }, default: {}, }), }}> <Tabs.Screen name="index" options={{ title: 'Home', tabBarIcon: ({ color }) => ( <IconSymbol size={28} name="house.fill" color={color} /> ), }} /> </Tabs> ); }
(auth)/_layout.tsx
// (auth)/_layout.tsx export default function RootLayout() { const colorScheme = useColorScheme(); const [loaded] = useFonts({ SpaceMono: require('../../assets/fonts/SpaceMono-Regular.ttf'), }); useEffect(() => { if (loaded) { SplashScreen.hideAsync(); } }, [loaded]); if (!loaded) { return null; } return ( <Stack screenOptions={{ headerShown: false }}> <Stack.Screen name="index" options={{ title: 'Sign In' }} /> </Stack> ); }
这样调整后,应该就能正常根据条件切换(tabs)和(auth)栈了。
内容来源于stack exchange

