How to use protected routes with firebase authentication without the context api/redux?

Viewed 17

I have made a simple React app in which a user can log in with their email and password using firebase. Now, when the user is logged in, I want them to be able to access the route /profile which should be inaccessible to users who aren't logged in.

My App.js looks like:

import { useEffect, useState } from "react";
import { getAuth, onAuthStateChanged } from "firebase/auth";

import { Routes, Route, Navigate } from "react-router-dom";

function App() {

  const ProtectedRoute = ({ user, children }) => {
    if (!currUser) {
      return <Navigate to="/" replace />;
    }

    return children;
  };

  return (
    <div>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="signin" element={<SignIn />} />
        <Route path="signup" element={<Signup />} />
        <Route
          path="/profile"
          element={
            <ProtectedRoute user={currUser}>
              <Profile />
            </ProtectedRoute>
          }
        />
        <Route path="*" element={<p>There's nothing here: 404!</p>} />
      </Routes>
    </div>
  );
}

export default App;

Now I read the firebase documentation regarding getting the current user and they recommend using the following way to get the current logged in user.

import { getAuth } from "firebase/auth";

const auth = getAuth();
const user = auth.currentUser;

if (user) {
  // User is signed in, see docs for a list of available properties
  // https://firebase.google.com/docs/reference/js/firebase.User
  // ...
} else {
  // No user is signed in.
}

So, if I combine both of these methods, the code becomes:

import { useEffect, useState } from "react";
import { getAuth, onAuthStateChanged } from "firebase/auth";

import { Routes, Route, Navigate } from "react-router-dom";

function App() {
    const auth = getAuth();
    const currUser = auth.currentUser;

  const ProtectedRoute = ({ user, children }) => {
    if (!currUser) {
      return <Navigate to="/" replace />;
    }

    return children;
  };

  return (
    <div>
      <Routes>
        <Route path="/" element={<HomePage />} />
        <Route path="signin" element={<SignIn />} />
        <Route path="signup" element={<Signup />} />
        <Route
          path="/profile"
          element={
            <ProtectedRoute user={currUser}>
              <Profile />
            </ProtectedRoute>
          }
        />
        <Route path="*" element={<p>There's nothing here: 404!</p>} />
      </Routes>
    </div>
  );
}

export default App;

My question: The above method doesn't work. It's probably because as soon as I try to get to /profile, currUser is null and the protected route works as it should. But after a while, I'm sure currUser gets set to the actual user but by then, we have already been redirected to the / page.

I checked this out online, and I saw a solution where someone was using Context API and was storing the current logged in user in a global context. Since I'm not using Context API/Redux, how do I get this to work?

0 Answers
Related