I made a protected route with react router for authentication. It redirects user to the blogs page after login/register. But when I refresh the blogs page, It takes me again to login page. I want stay on the blogs page after refresh. How should I do it? I used react router hooks, firebase, react bootstrap
<Route
path="/blogs"
element={
<RequireAuth>
<Blogs></Blogs>
</RequireAuth>
}
></Route>
RequireAuth file -
import React from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import { Navigate, useLocation } from "react-router-dom";
import auth from "../../firebase.init";
function RequireAuth({ children }) {
const [user] = useAuthState(auth);
let location = useLocation();
if (!user) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
}
export default RequireAuth;
login page -
import { Link, useLocation, useNavigate } from "react-router-dom";
const Login = () => {
let navigate = useNavigate();
let location = useLocation();
let from = location.state?.from?.pathname || "/";
const handleSubmit = async (event) => {
// firebase login code
navigate(from, { replace: true });
};
return (
<Form onSubmit={handleSubmit}>
</Form>
);
};
export default Login;
I solved this issue by handling an extra loading
state on the RequireAuth
component.
RequireAuth.jsx
file
import React from "react";
import { useAuthState } from "react-firebase-hooks/auth";
import { Navigate, useLocation } from "react-router-dom";
import auth from "../../firebase.init";
function RequireAuth({ children }) {
const [user, loading] = useAuthState(auth); // change here
let location = useLocation();
// handling loading state to not redirect after page reload.
if (loading) {
return <div> Loading <div/>
}
if (!user) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
return children;
}
export default RequireAuth;
By adding a loading
state it prevents the code from running when the login is still in progress. Because the first time when the page loads useAuthState
which is supposed to monitor the user, it returns user = null
. That is why this line -
if (!user) {
return <Navigate to="/login" state={{ from: location }} replace />;
}
runs and redirects the user to the login page.
After the page loads and when useAuthState
is again called automatically, it returns the user = user
. This means the user is here and it returns children, in my case Blogs
component.