skip to Main Content

I’m working on a React Native project using expo-router, and I’m having an issue with conditional routing based on the session state. I want to navigate to a login screen (auth.tsx) if there’s no active session, or to a tab-based screen ((tabs)/index.tsx) if the user is logged in.

Problem:

  • The app always seems to navigate to the index.tsx file, even though I’m using expo-router with conditional routing based on session state.
  • When I check the session state, it’s correctly logged, but the route isn’t behaving as expected.
  • Additionally, when I try to sign out using router.push(‘app/auth.tsx’), the navigation doesn’t work, and it returns an error that the route could not be found.

Please help me out.

    // app/_layout.tsx (this is the root layout)
    import React, { useEffect } from 'react';
    import { View, Text } from 'react-native';
    import { Stack } from 'expo-router';
    import { useAuth } from '../context/AuthContext';

    function AppContent() {
      const { session, isLoading } = useAuth();

      if (isLoading) {
        return (
          <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
            <Text>Loading...</Text>
          </View>
        );
      }

      return (
        <Stack screenOptions={{ headerShown: false }}>
          {!session || !session.user ? ( // this does not work
            // Navigate to auth if session is null, undefined, or invalid
            <Stack.Screen name="auth" options={{ headerShown: false }} />
          ) : (
            // Navigate to (tabs) if session and user are valid
            <Stack.Screen name="(tabs)" options={{ headerShown: false }} />
          )}
        </Stack>
      );
    }

    export default function App() {
      return (
        <AuthProvider>
          <AppContent />
        </AuthProvider>
      );
    }

I’ve made sure that the file structure matches expo-router conventions:

    /app
      ├── auth.tsx          // Login screen
      ├── _layout.tsx       // Root layout
      └── (tabs)
          └── index.tsx     // Tab-based screen
          └── _layout.tsx   // Tab-based layout

Sign Out Buttons:

    <TouchableOpacity onPress={async () => {
        try {
            const { error } = await supabase.auth.signOut();
            if (error) {
                    console.error('Error signing out:', error.message);
                } else {
                    console.log('Successfully logged out');
                    // Sign out the user
                    await router.push('../../app/auth.tsx'); 
                 }
             } catch (err) {
                 console.error('Unexpected error during sign out:', err);
                 }
         }}>
             <Text style={[styles.drawerItem, styles.logout]}>Logout</Text>
    </TouchableOpacity>
    <Button
        title="Sign Out"
        onPress={async () => {
            await supabase.auth.signOut(); // Sign out the user
            router.push('/app/Auth.tsx'); // Navigate to the Auth page
        }}
        color="#34d399"
    />

2

Answers


  1. router.push('/app/Auth.tsx'); ===>router.push('/app/auth.tsx');
    
    Login or Signup to reply.
  2. For your specific case, you can try using the redirect prop (although there could be a better way to achieve this).

    In the root layout component you have pasted, try the following (notice the redirect prop for the second screen):

    return (
        <Stack screenOptions={{ headerShown: false }}>
          <Stack.Screen name="auth" options={{ headerShown: false }} />
          <Stack.Screen name="(tabs)" options={{ headerShown: false }} redirect={!session || !session.user} />
        </Stack>
      );
    

    This way, whenever the value of session gets altered and the redirect condition is satisfied (which you have confirmed it does), you will be redirected to the auth route.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search