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

React Native Expo File Router初始路由设置:引导页未生效

问题:如何让Expo Router项目启动默认打开Onboarding引导页?

我用npx create-expo-app@latest创建了React Native项目,项目自带tabs模板页面。已经创建了onboarding.tsx引导页,希望应用启动时默认打开该页面,但目前应用仍打开(tabs)标签页。相关代码及文件路由结构如下:

onboarding.tsx代码

import React from "react";
import { View, Text, Button } from "react-native";
import { useRouter } from "expo-router";

export default function Onboarding() {
    const router = useRouter();

    const finishOnboarding = () => {
        router.replace("/");
    };

    return (
        <View
            style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
            <Text>Welcome to the app!</Text>
            <Button title="Get Started" onPress={finishOnboarding} />
        </View>
    );
}

app/_layout.tsx代码

import {
    DarkTheme,
    DefaultTheme,
    ThemeProvider,
} from "@react-navigation/native";
import { useFonts } from "expo-font";
import { Stack } from "expo-router";
import * as SplashScreen from "expo-splash-screen";
import { useEffect } from "react";
import "react-native-reanimated";

import Onboarding from "./onboarding";

import { useColorScheme } from "@/hooks/useColorScheme";

SplashScreen.preventAutoHideAsync();

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 (
        <ThemeProvider
            value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
            <Stack initialRouteName="/onboarding">
                <Stack.Screen
                    name="onboarding"
                    options={{ headerShown: false }}
                />
                <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
                <Stack.Screen name="+not-found" />
            </Stack>
        </ThemeProvider>
    );
}

文件路由结构

app
/(tabs)
       /_layout.tsx
       /explore.tsx
       /index.tsx
/_layout.tsx
/onboarding.tsx
/+html.tsx
/+not-found.tsx

原因分析

  1. initialRouteName取值错误:Expo Router的Stack组件中,initialRouteName需要匹配Stack.Screen定义的name属性值,而非带斜杠的路径。你当前设置的"/onboarding"是错误的,正确值应为"onboarding"。
  2. 默认路由优先级:Expo Router默认会优先选择(tabs)分组路由或根目录下的index.tsx作为初始页面,当initialRouteName设置错误时,就会触发这个默认行为。

解决方案

1. 修正initialRouteName的值

修改app/_layout.tsx中的Stack组件配置,将initialRouteName="/onboarding"改为initialRouteName="onboarding":

// 修正后的Stack部分代码
<Stack initialRouteName="onboarding">
    <Stack.Screen
        name="onboarding"
        options={{ headerShown: false }}
    />
    <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
    <Stack.Screen name="+not-found" />
</Stack>

2. (可选)持久化引导页状态(避免重复显示)

如果需要用户完成引导后不再显示,可以用AsyncStorage存储状态,在RootLayout中判断跳转:

首先安装依赖:

npx expo install @react-native-async-storage/async-storage

修改app/_layout.tsx:

import AsyncStorage from '@react-native-async-storage/async-storage';
import React from 'react';
// ... 其他导入

export default function RootLayout() {
    const colorScheme = useColorScheme();
    const [loaded] = useFonts({
        SpaceMono: require("../assets/fonts/SpaceMono-Regular.ttf"),
    });
    const [hasSeenOnboarding, setHasSeenOnboarding] = React.useState(false);

    useEffect(() => {
        const checkOnboardingStatus = async () => {
            const status = await AsyncStorage.getItem('hasSeenOnboarding');
            setHasSeenOnboarding(status === 'true');
        };
        checkOnboardingStatus();
    }, []);

    useEffect(() => {
        if (loaded) {
            SplashScreen.hideAsync();
        }
    }, [loaded]);

    if (!loaded) {
        return null;
    }

    return (
        <ThemeProvider
            value={colorScheme === "dark" ? DarkTheme : DefaultTheme}>
            <Stack initialRouteName={hasSeenOnboarding ? "(tabs)" : "onboarding"}>
                <Stack.Screen
                    name="onboarding"
                    options={{ headerShown: false }}
                />
                <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
                <Stack.Screen name="+not-found" />
            </Stack>
        </ThemeProvider>
    );
}

同时修改onboarding.tsx中的完成函数,存储状态:

import AsyncStorage from '@react-native-async-storage/async-storage';

// ...

const finishOnboarding = async () => {
    await AsyncStorage.setItem('hasSeenOnboarding', 'true');
    router.replace("/");
};

内容的提问来源于stack exchange,提问作者Tan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:34:54