Expo router with authentication conditional rendering

322 Views Asked by At

I use Expo router and am having trouble creating protected routes when working with authentication. I have a provider and global state for the current user logged in, which is working fine.

When I log in, i use router.replace("/") which takes me to the correct screen (profile). If I sign out from the profile screen (i.e. setting the global user state to null nothing happens. It doesn't rerender, and allows the user to still see the protected route.

If I console.log the user object it says null.

Video showing me signing in then signing out, without any rerender

See file structure and return statements below.


- app (root folder)
- (app)
  - _layout.tsx
  - (tabs)
     - _layout.tsx
     - chat.tsx
     - profile.tsx

- login.tsx
- signup.tsx
- _layout.tsx

Inside /_layout.tsx (root) i have the following, where I declare all my Screens and provide the global state of the current user:

  <FirebaseAuthProvider>
        <Stack>
          <Stack.Screen name='login'/>
          <Stack.Screen name="signup"/>
          <Stack.Screen name="(app)"/>
        </Stack>
    </FirebaseAuthProvider>

Inside (app)/_layout.tsx have the following, where I conditionally redirect if the user is not logged in:

if(auth.isLoading){
    return <Text>Laddar</Text>
  }

  if(auth.user)
  {
  return <Redirect href="/login"/>
  }

  return (
    
      <Stack>
        <Stack.Screen name="(tabs)" options={{ headerShown: false }} /> 
      </Stack>
    
  )
2

There are 2 best solutions below

0
kingkong.js On BEST ANSWER

There was an issue with my isLoading, which did not update the state correctly. Once I fixed that, everything worked.

0
John McCants On

There are a few different options to have the profile recognize that there isn’t a user. You can simply call router.replace(‘/login’) in the logout function. You could create an AuthProvider that runs this useEffect when the user changes.

useEffect(() => {
 
 if (!user) router.replace(“/login”)

}, [user])

Or you could put this useEffect in your profile screen and it should work.