'Firebase onAuthStateChange() not working, still being redirected to login page on refresh

Hi there I'm still new to ReactJS and I've just started using Firebase, where I'm currently following along a tutorial; The issue that I'm facing is that every time I refresh the page I'm thrown back to my sign in page, I've also created protected routes to check whether the user is logged in or not but this wouldn't be the case, as I've been shuffling the onAuthStateChange() around to see whether it's not firing before hand, but I'm still stuck in the rabbit hole.

"Take note I am using firebase v9"

My userAuth() context

import { createContext, useContext, useEffect, useState } from "react";
import { auth } from '../config/firebase';
import {
    createUserWithEmailAndPassword,
    signInWithEmailAndPassword,
    signOut,
    onAuthStateChanged,
    confirmPasswordReset,
    sendPasswordResetEmail,
    GoogleAuthProvider,
    signInWithPopup
} from 'firebase/auth';

const userAuthContext = createContext();

export function UserAuthContextProvider({children}){
    const [user, setUser] = useState(null);

    function signUp(email, password){
        return createUserWithEmailAndPassword(auth, email, password);
    }

    function signIn(email, password){
        return signInWithEmailAndPassword(auth, email, password);
    }

    function googleSignIn(){
        const provider = new GoogleAuthProvider();
        return signInWithPopup(auth, provider)
    }

    function logOut(){
        return signOut(auth);
    }

    function forgotPassword(email){
        return sendPasswordResetEmail(auth, email, {url:'http://localhost:3000/signin'});
    }

    function resetPassword(oobCode, newPassword){
        return confirmPasswordReset(auth, oobCode, newPassword);
    }

    useEffect(() => {
        const unsubscribe = onAuthStateChanged(auth, (currentUser) => {
            setUser(currentUser);
        })

        return () => {
            unsubscribe();
        }
    },[]);

    return (
        <userAuthContext.Provider value={{
            user, 
            signIn, 
            googleSignIn, 
            signUp, 
            logOut, 
            forgotPassword,
            resetPassword}}
        >
            {children}
        </userAuthContext.Provider>
    )
}

export function UserAuth(){
    return useContext(userAuthContext);
}

My Protected Route

import { Redirect, Route } from "react-router-dom";
import { UserAuth } from "../../context/userAuth";

const ProtectedRoute = ({component: Component, ...rest}) => {
  const {user} = UserAuth();
  
  return (
    <Route
    {...rest}
    render={(props) => 
        user ? (
          <Component {...props}/>
        ):(
          <Redirect to="/signin"/>
        ) 
      }
    />
  )
}

export default ProtectedRoute

I've wrapped the UserAuthContextProvider in index.js

ReactDOM.render(
  <UserAuthContextProvider>
    <App />
  </UserAuthContextProvider>,
  document.getElementById('root')
);


Solution 1:[1]

It's normal, when you refreshed the page you lost the state of the app. Use localstorage to store user.

  useEffect(() => {
    let unsubscribe;
    const user = localStorage.getItem('user'); // <=== save the state in localStorage

    if (user) {
      setUser(JSON.parse(user));
    } else {
      unsubscribe = onAuthStateChanged(auth, (currentUser) => {
        setUser(currentUser);
        localStorage.setItem('user', JSON.stringify(user));
      });
    }
 
    return () => {
      if(unsubscribe) unsubscribe();
    };
  }, []);

 

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Soufiane Boutahlil