You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

仅一个NavigationContainer却触发嵌套错误,Expo Router环境求解决

解决NavigationContainer嵌套报错(Expo Router与React Navigation混用问题)

报错信息

错误:看起来你在一个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 08:47:03