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

React Native认证路由问题:AuthStack仍挂载于RootStack之上求助

问题分析

你的问题核心在于Expo Router的分组路由机制与手动条件渲染Stack组件的冲突。Expo Router的(auth)和(root)分组本身已经是独立的导航栈,直接在Root组件中条件返回RootStack或AuthStack会导致两个栈被同时挂载(前一个栈未被卸载),从而出现AuthStack页面叠加在RootStack之上的情况。

解决方案

我们需要利用Expo Router的路由跳转能力重置导航栈,而非手动渲染不同Stack组件。以下是具体修改步骤:

1. 移除手动定义的RootStack和AuthStack

Expo Router会根据文件目录结构自动生成导航栈,(auth)和(root)分组已作为独立栈存在,无需手动创建Stack组件。

2. 修改Root组件逻辑:用路由跳转替代条件渲染

当认证状态确定后,使用router.replace跳转到对应路由,重置导航栈,避免之前的栈残留。

修改后的完整代码

import { router, Slot, Stack } from "expo-router";
import { StatusBar } from "expo-status-bar";
import { useContext, useEffect, useState } from "react";
import { AuthContext, AuthContextProvider } from "../context/AuthContext";
import { ActivityIndicator, View } from "react-native";
import AsyncStorage from "@react-native-async-storage/async-storage";
import { getUserInforWithToken } from "../controller/AuthController";

function Root() {
  const { setIsLogin, setToken } = useContext(AuthContext);
  const [isLoading, setIsLoading] = useState(true);

  useEffect(() => {
    const checkAuth = async () => {
      const token = await AsyncStorage.getItem("token");
      if (token) {
        console.log("token found, user logged in");
        setIsLogin(true);
        setToken(token);
        // 跳转到root分组首页,重置导航栈
        router.replace("/(root)/index");
      } else {
        setIsLogin(false);
        // 跳转到auth分组登录页,重置导航栈
        router.replace("/(auth)/index");
      }
    };

    checkAuth().finally(() => {
      setIsLoading(false);
    });
  }, []);

  if (isLoading) {
    console.log("Loading...");
    return (
      <View className="flex-1 justify-center items-center">
        <ActivityIndicator className="p-2 m-2" animating size="large" />
      </View>
    );
  }

  // 用Slot渲染当前路由匹配的页面,由Expo Router自动处理
  return <Slot />;
}

export default function Layout() {
  return (
    <AuthContextProvider>
      <StatusBar style="light" />
      {/* 配置全局Stack默认选项,统一管理头部样式 */}
      <Stack screenOptions={{ headerShown: false }}>
        <Stack.Screen name="(auth)" />
        <Stack.Screen name="(root)" />
      </Stack>
      <Root />
    </AuthContextProvider>
  );
}

关键改动说明

  • 依赖自动路由栈:移除手动Stack组件,让Expo Router根据(auth)、(root)分组自动生成独立导航栈。
  • router.replace重置栈:该方法会替换当前导航栈顶部页面并重置整个栈,彻底避免旧栈残留。
  • Slot渲染页面:Expo Router核心组件,负责渲染当前路由匹配的页面,确保路由系统正常工作。
  • 简化加载逻辑:在checkAuth的finally中直接设置加载状态结束,无需额外监听isTryingLogin(若该状态无其他用途可从AuthContext中移除)。

额外建议

  • 确保文件目录结构符合Expo Router要求:
    app/
      (auth)/
        index.jsx   # 登录页
        signup.jsx  # 注册页
      (root)/
        index.jsx   # 首页
      _layout.jsx   # 你的Layout组件所在文件
    
  • 保持AuthContext中isLogin状态同步,避免状态不一致引发路由异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 23:42:43