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
相关产品推荐
相关产品推荐

