Everything auth-wise is working fine. I even have a loading state setup so that the loader shows until the state is changed, but I still get this flickering on reload. This flickering only happens with Supabase. I was using the Firebase version before and it worked perfectly with my code.
Here is a video for reference: https://i.sstatic.net/rxGDn.jpg
Edit: Updated code to current version
export default function Navigation() {
const { user, setUser } = useContext(AuthenticatedUserContext);
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
const session = supabase.auth.session();
setUser(session?.user ?? null);
const { data: listener } = supabase.auth.onAuthStateChange((_: any, session: any) => {
setUser(session?.user ?? null);
});
setIsLoading(false);
return () => {
listener?.unsubscribe();
};
}, []);
if (isLoading) {
return (
<View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}>
<ActivityIndicator color={Theme.colors.purple} size="large" />
</View>
);
}
return (
<NavigationContainer linking={LinkingConfiguration}>{user ? <AppStack /> : <AuthStack />}</NavigationContainer>
);
}
Ok, Supabase has released some updates since I first asked this question. Here is how I am now able to stop flickering when loading the application.
First, we need to set up our AuthContext for our application. Be sure to wrap your App.tsx
with the <AuthContextProvider>
.
AuthContext.tsx
import React, { createContext, useContext, useEffect, useState } from 'react';
import { Session, User } from '@supabase/supabase-js';
import { supabase } from '../config/supabase';
export const AuthContext = createContext<{ user: User | null; session: Session | null }>({
user: null,
session: null,
});
export const AuthContextProvider = (props: any) => {
const [userSession, setUserSession] = useState<Session | null>(null);
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
supabase.auth.getSession().then(({ data: { session } }) => {
setUserSession(session);
setUser(session?.user ?? null);
});
const { data: authListener } = supabase.auth.onAuthStateChange(async (event, session) => {
console.log(`Supabase auth event: ${event}`);
setUserSession(session);
setUser(session?.user ?? null);
});
return () => {
authListener.subscription;
};
}, []);
const value = {
userSession,
user,
};
return <AuthContext.Provider value={value} {...props} />;
};
export const useUser = () => {
const context = useContext(AuthContext);
if (context === undefined) {
throw new Error('useUser must be used within a AuthContextProvider.');
}
return context;
};
Now, if you're using React Navigation like me we need to check if we have a valid user to send them to the logged-in home screen. Here's how I do it.
Navigation.tsx
export default function Navigation() {
const { user } = useUser();
return (
<NavigationContainer linking={LinkingConfiguration}>
{user ? <AppStackNavigator /> : <AuthStackNavigator />}
</NavigationContainer>
);
}