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

React Native使用react-navigation导航跳转异常问题求助

解决方案

问题核心原因

你的问题本质是LoadPage作为导航栈的常驻入口页,同时Supabase会话状态变化时会触发LoadPage的跳转逻辑,和登录/登出时的手动跳转形成冲突,导致每次状态变更都会先回到LoadPage再跳转目标页。下面是两种直接解决的方案:


方案1:将LoadPage作为临时加载组件(推荐)

把LoadPage从导航栈中移除,仅作为应用初始化时的临时加载UI,会话确认后直接渲染目标页面栈,彻底避免重复跳转。

导航结构代码

import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { useEffect, useState } from 'react';
import { supabase } from './supabase';
import LoadPage from './LoadPage';
import Welcome from './Welcome';
import Dashboard from './Dashboard';

const Stack = createNativeStackNavigator();

export default function App() {
  const [session, setSession] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    // 监听会话状态变化
    const { data: listener } = supabase.auth.onAuthStateChange((_event, session) => {
      setSession(session);
      setLoading(false);
    });

    // 初始化获取当前会话
    const getInitialSession = async () => {
      const { data } = await supabase.auth.getSession();
      setSession(data.session);
      setLoading(false);
    };

    getInitialSession();
    return () => listener.unsubscribe();
  }, []);

  // 加载状态时显示LoadPage
  if (loading) {
    return <LoadPage />;
  }

  // 根据会话状态渲染对应页面栈
  return (
    <NavigationContainer>
      <Stack.Navigator screenOptions={{ headerShown: false }}>
        {session ? (
          <Stack.Screen name="Dashboard" component={Dashboard} />
        ) : (
          <Stack.Screen name="Welcome" component={Welcome} />
        )}
      </Stack.Navigator>
    </NavigationContainer>
  );
}

登录/登出逻辑简化

登录和登出时无需手动调用导航方法,会话状态变化会自动触发页面切换:

// Welcome页登录逻辑
const handleLogin = async () => {
  const { error } = await supabase.auth.signInWithPassword({
    email,
    password,
  });
  if (error) alert(error.message);
};

// Dashboard页登出逻辑
const handleLogout = async () => {
  const { error } = await supabase.auth.signOut();
  if (error) alert(error.message);
};

方案2:保留LoadPage作为入口页(兼容原有结构)

如果必须保留LoadPage在导航栈中,需要限制其跳转逻辑只执行一次,避免会话变化时重复触发:

LoadPage代码修改

import { useEffect, useState } from 'react';
import { View, ActivityIndicator } from 'react-native';
import { supabase } from './supabase';
import { useNavigation } from '@react-navigation/native';

export default function LoadPage() {
  const navigation = useNavigation();
  const [hasCheckedSession, setHasCheckedSession] = useState(false);

  useEffect(() => {
    // 仅初始加载时检查一次会话
    const checkInitialSession = async () => {
      if (hasCheckedSession) return;
      
      const { data } = await supabase.auth.getSession();
      if (data.session) {
        navigation.replace('Dashboard');
      } else {
        navigation.replace('Welcome');
      }
      setHasCheckedSession(true);
    };

    checkInitialSession();

    // 后续会话变化直接跳转目标页,不再回到LoadPage
    const { data: listener } = supabase.auth.onAuthStateChange((event) => {
      if (!hasCheckedSession) return;
      
      if (event === 'SIGNED_IN') {
        navigation.replace('Dashboard');
      } else if (event === 'SIGNED_OUT') {
        navigation.replace('Welcome');
      }
    });

    return () => listener.unsubscribe();
  }, [hasCheckedSession, navigation]);

  return (
    <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
      <ActivityIndicator size="large" />
    </View>
  );
}

导航结构设置

<Stack.Navigator initialRouteName="LoadPage" screenOptions={{ headerShown: false }}>
  <Stack.Screen name="LoadPage" component={LoadPage} />
  <Stack.Screen name="Welcome" component={Welcome} />
  <Stack.Screen name="Dashboard" component={Dashboard} />
</Stack.Navigator>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 07:35:54