I'm making an app, where I use NextJS along with Firebase, Fireauth. The problem is that the user isn't available as soon as the page reloads or loads, it takes time to load, till then useEffect
also fails to identify if user exists or not and just decides user doesn't exist.
This is my code
import { useAuth } from '/pages/contexts/AuthContexts';
const { user } = useAuth();
const router = useRouter();
const [loading, setLoading] = useState(true);
useEffect(() => {
console.log('updating user')
if (user) {
console.log(user);
setLoading(false)
} else {
console.log('no user')
}
}, [user, router]);
useEffect(() => {
if (!loading && typeof user !== 'undefined') {
console.log('yes user')
}else{
console.log('no user')
}
}, [loading]);
Here i first see no user, then after a while i see yes user, the loading state isnt helping at all
This is my useAuth file
// contexts/AuthContext.js
import { createContext, useContext, useState, useEffect } from 'react';
import { onAuthStateChanged } from 'firebase/auth';
import { auth } from 'flubel/firebase';
const AuthContext = createContext();
export const AuthProvider = ({ children }) => {
const [user, setUser] = useState(null);
useEffect(() => {
const unsubscribe = onAuthStateChanged(auth, (user) => {
setUser(user);
});
return () => {
unsubscribe();
};
}, []);
return (
<AuthContext.Provider value={{ user, setUser }}>
{children}
</AuthContext.Provider>
);
};
export const useAuth = () => {
return useContext(AuthContext);
};
I tried creating multiple states but they all return no user no matter how I handle the states, I can't use setTimeout because, slow internet connection could also be a problem.
While the Firebase Authentication client keeps the credentials in local storage, it needs to check with the server whether those credentials and account are valid (for example: it could've been disabled). And since that call takes time:
onAuthStateChanged
event when the call to the server has completed.There is nothing in the Firebase Authentication SDK to change this behavior, as it it working correctly on that level.
But in an application you may be willing to make another trade-off. For example, if the user was signed in before - most of the time the above flow will complete successfully. So on an application level you can decide to assume that the sign-in will completely successfully in that scenario.
If that is something you're interested in, you can implement it was follows:
onAuthStateChanged
callback), revers the decission and redirect to the "you're not signed in" UI. This will result in a UI flash, but it'll be much less common.Also see When the page is reloaded, firebase.auth.currentUser returns null, where I explained this before.