title: Login with Firebase and React Router Dom (How to use onAuthStateChanged)
body: <p>I am a beginner in react and I have a problem here. I try to make website that have login page. I use firebase for authenticate my website. The problem is, how to implement <code>onAuthStateChange</code> to <code>react-router</code>. BTW I used Redux.</p>
  <p>This is my App.js file:</p>
  <pre><code>import React, { useEffect } from 'react';
  import { Routes, Route, Navigate } from 'react-router-dom';
  import { useDispatch, useSelector } from 'react-redux';
  import {
    createUserDocumentFromAuth,
    onAuthStateChangedListener,
  } from './utils/firebase/Firebase.utils';
  
  import { setCurrentUser } from './store/action';
  
  import './App.scss';
  
  import Page from './routes/Page';
  import Authentication from './routes/Authentication';
  
  function App() {
    const dispatch = useDispatch();
    const currentUser = useSelector(state =&gt; state.currentUser);
  
    const ProtectedRoutes = ({children }) =&gt; {
      if (!currentUser) {
        return &lt;Navigate to=&quot;auth&quot; replace /&gt;
      }
      return children
    }
  
    useEffect(() =&gt; {
      const unsubscribe = onAuthStateChangedListener(user =&gt; {
        if (user) {
          createUserDocumentFromAuth(user);
        }
        dispatch(setCurrentUser(user));
      });
  
      return unsubscribe;
    }, [dispatch]);
  
    return (
      &lt;Routes&gt;
        &lt;Route
          index
          element={
            &lt;ProtectedRoutes&gt;
              &lt;Page /&gt;
            &lt;/ProtectedRoutes&gt;
          }
        /&gt;
        &lt;Route path=&quot;auth&quot; element={&lt;Authentication /&gt;} /&gt;
      &lt;/Routes&gt;
    );
  }
  
  export default App;
  </code></pre>
  <p>I've investigated, what the problem is. I did console what the <code>currentUser</code> is, in first render it returns null, and after that it returns something. I think my <code>ProtectedRoutes</code> is correct, but now how to get the last state from current user. Or any alternative ways to solve this? BTW, this is my firebase.utils file:</p>
  <pre><code>import { initializeApp } from 'firebase/app';
  import {
    getAuth,
    GoogleAuthProvider,
    signInWithPopup,
    createUserWithEmailAndPassword,
    signInWithEmailAndPassword,
    signOut,
    onAuthStateChanged,
  } from 'firebase/auth';
  import {
    getFirestore,
    doc,
    getDoc,
    setDoc,
    collection,
    writeBatch,
    query,
    getDocs,
  } from 'firebase/firestore';
  
  const firebaseConfig = {
    apiKey: &quot;......&quot;,
    authDomain: &quot;......&quot;,
    projectId: &quot;......&quot;,
    storageBucket: &quot;......&quot;,
    messagingSenderId: &quot;......&quot;,
    appId: &quot;......&quot;
  };
  
  const app = initializeApp(firebaseConfig);
  
  const provider = new GoogleAuthProvider();
  
  provider.setCustomParameters({
    propmt: 'select_account',
  });
  
  export const auth = getAuth();
  export const signInWithGooglePopup = () =&gt; signInWithPopup(auth, provider);
  
  export const db = getFirestore();
  
  export const addCollectionAndDocuments = async (collectionKey, objectsToAdd) =&gt; {
    const collectionRef = collection(db, collectionKey);
    const batch = writeBatch(db);
  
    objectsToAdd.forEach((object) =&gt; {
      const docRef = doc(collectionRef, object.title.toLowerCase())
      batch.set(docRef, object)
  
    })
  
    await batch.commit()
  }
  
  export const getCategoriesAndDocuments = async () =&gt; {
    const collectionRef = collection(db, 'categories')
    const q = query(collectionRef);
  
    const querySnapshot = await getDocs(q)
    const categoryMap = querySnapshot.docs.reduce((acc, docSnapshot) =&gt; {
      const { title, items } = docSnapshot.data()
      acc[title.toLowerCase()] = items;
      return acc
    }, {})
  
    return categoryMap
  }
  
  export const createUserDocumentFromAuth = async (
    userAuth,
    additionalInformation = {}
  ) =&gt; {
    if (!userAuth) return;
  
    const userDocRef = doc(db, 'users', userAuth.uid);
    const userSnapshot = await getDoc(userDocRef);
  
    if (!userSnapshot.exists()) {
      const { displayName, email } = userAuth;
      const createdAt = new Date();
  
      try {
        await setDoc(userDocRef, {
          email,
          displayName,
          createdAt,
          ...additionalInformation,
        });
      } catch (error) {
        console.log('error creating the user.', error.message);
      }
    }
  
    return userDocRef;
  };
  
  export const createUserAuthWithEmailAndPassword = async (email, password) =&gt; {
    if (!email || !password) return;
  
    return createUserWithEmailAndPassword(auth, email, password);
  };
  
  export const signInUserAuthWithEmailAndPassword = async (email, password) =&gt; {
    if (!email || !password) return;
  
    return signInWithEmailAndPassword(auth, email, password);
  };
  
  export const signOutUser = async () =&gt; await signOut(auth);
  
  export const onAuthStateChangedListener = callback =&gt;
    onAuthStateChanged(auth, callback);
  </code></pre>