When a user logs in, I want to check if he has created his business or not. If he hasn’t he should be navigated to the onboarding page. The page keeps refreshing as if there’s a loop going on. Someone advised I put this in the protected route file. I tried doing it this way:
Homepage.jsx
const { message} = useSelector(
(state) => state.auth
);
useEffect(() => {
if (message !== "This user does not have a business account, please create one and continue") {
navigate("/auth/onboarding");
}
}, [message, navigate])
I have this useEffect in the onboarding page. I suspect the loop comes from here because this toast message appears.
useEffect(() => {
if (isError) {
toast({
title: "Error",
description: message,
status: "error",
position: "top-right",
duration: 5000,
isClosable: true,
});
}
if (isSuccess || organization) {
toast({
title: "Congrats!🎉",
description: "Onboarding completed.",
status: "success",
position: "top-right",
duration: 15000,
isClosable: true,
});
navigate("/");
}
}, [organization, isError, isSuccess, navigate, dispatch]);
ProtectedRoute.jsx
import { Navigate, Outlet, useLocation } from "react-router-dom";
import { useSelector } from "react-redux";
export default function ProtectedRoutes() {
const location = useLocation();
const { user } = useSelector((store) => store.auth);
let userid = localStorage.getItem("user") == null ? false : true;
return <div>{userid ? <Outlet /> : <Navigate to="/auth/login" />}</div>;
}
Included what i tried above.
2
Answers
One thing to note here is your use of
useEffect
andreturn
calls. Generally,return
calls inuseEffect
are intended for cleanup functions, and are performed on render, or on unmount. This could have adverse effects on your redirect. Try removing thereturn
and simply calling the redirect on the condition.A far simpler implementation of this is not to use an effect.
If the message requires a redirect, return a Redirect component (declarative redirect), if the message doesn’t require a redirect, return the actual component you want to render
You’ll avoid a flash of content and you’ll also enjoy simpler logic in your child component because it no longer has to consider if the user also needs to be redirected or not, that’ll be handled in the parent
TL;DR – if you’re trying to redirect a user away from a component they shouldn’t be accessing, you’ve already lost. The logic that prevents them from accessing the component in the first place should be elsewhere, not in the component they shouldn’t be accessing