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?