仅一个NavigationContainer却触发嵌套错误,Expo Router环境求解决
报错信息
错误:看起来你在一个NavigationContainer中嵌套了另一个。通常应用的根节点只需要一个容器,这大概率是个错误。如果是有意为之,请显式传递'independent={true}'。注意这会使子导航器与父导航器断开,无法在它们之间跳转。
问题根源
你同时混用了Expo Router和原生React Navigation的导航体系。Expo Router本身已经内置了NavigationContainer,而你在index.js里手动添加了一个,再加上_layout.js中Expo Router的Stack组件,导致导航容器嵌套触发报错。同时你在home.js中使用的Stack.Screen是原生React Navigation的写法,和Expo Router的导航逻辑冲突。
解决方案
1. 重构index.js作为首页
移除原生React Navigation的冗余代码,把index.js作为Expo Router的首页:
import { View, ScrollView, SafeAreaView } from 'react-native'; import { useRouter } from 'expo-router'; import { COLORS, SIZES } from '../constants'; import { ScreenHeaderBtn, TimeSlider, SessionBtn } from '../myComponents'; const Home = () => { const router = useRouter(); return ( <SafeAreaView style={{ flex: 1, backgroundColor: COLORS.lightBeige }}> <ScrollView showsVerticalScrollIndicator={false}> <View style={{ flex: 1, padding: SIZES.medium }}> <View style={{ alignItems: 'center', padding: SIZES.xLarge }}> <SessionBtn /> </View> <View style={{ alignItems: 'center', padding: SIZES.xLarge }}> <TimeSlider /> </View> </View> </ScrollView> </SafeAreaView> ); }; export default Home;
2. 在_layout.js中统一配置导航栈与Header
Expo Router的_layout.js是导航根配置,在这里定义页面路由和Header选项:
import { Stack } from 'expo-router'; import { useCallback } from 'react'; import { useFonts } from 'expo-font'; import * as SplashScreen from 'expo-splash-screen'; import { Text } from 'react-native'; import { COLORS, icons } from '../constants'; import { ScreenHeaderBtn } from '../myComponents'; import styles from '../myComponents/common/header/header/header.style'; SplashScreen.preventAutoHideAsync(); const Layout = () => { const [fontsLoaded] = useFonts({ MontBold: require('../assets/fonts/Montserrat-Bold.ttf'), MontMed: require('../assets/fonts/Montserrat-Medium.ttf'), MontReg: require('../assets/fonts/Montserrat-Regular.ttf'), }); const onLayoutRootView = useCallback(async () => { if (fontsLoaded) await SplashScreen.hideAsync(); }, [fontsLoaded]); if (!fontsLoaded) return null; return ( <Stack onLayout={onLayoutRootView}> <Stack.Screen name="index" // 对应index.js页面路由 options={{ headerStyle: { backgroundColor: COLORS.lightBeige }, headerShadowVisible: true, headerLeft: () => ( <ScreenHeaderBtn iconUrl={icons.menu} dimension="60%" /> ), headerTitle: () => ( <Text style={styles.headerStyle}>Flowtime</Text> ), headerTitleAlign: 'center', }} /> </Stack> ); }; export default Layout;
3. 移除冗余的home.js
如果不需要单独的/home路由,直接删除home.js即可;若要保留,需在_layout.js中添加对应Stack.Screen并调整页面逻辑。
核心注意事项
- Expo Router基于React Navigation封装,无需手动添加
NavigationContainer,框架会自动处理根容器。 - 页面的Header配置必须放在
_layout.js的Stack.Screen的options中,不能在页面内部使用原生React Navigation的Stack.Screen。 - 除非有特殊场景需要独立导航栈,否则不要混用两种导航体系,优先使用Expo Router的统一路由逻辑。
内容的提问来源于stack exchange,提问作者ronbutan
相关产品推荐
相关产品推荐

