Reputation: 643
This is my app.js where all the routes
<Router>
<Routes>
<Route exact path="/" element={<Home />} />
<Route element={<PrivateRoute />}>
<Route exact path="/dashboard" element={<Dashboard />} />
<Route exact path="/payment" element={<Payment />} />]
</Route>
<Route exact path="/login" element={<Login />} />
</Routes>
</Router>
This is my PrivateRoute component
function PrivateRoute({ fetchMe, ...props }) {
const [type, setType] = useState("xxxxx");
const isAuthenticated = localStorage.getItem("authToken");
const navigate = useNavigate();
const [lodar, setLodar] = useState(false);
useEffect(() => {
setLodar(false);
if (isAuthenticated) {
(async () => {
const {
value: { user },
} = await fetchMe();
console.log({ data: user.step1 });
if (user.step === 1) {
navigate("/payment");
}
setLodar(false);
})();
}
}, []);
return (
<Spin indicator={antIcon} spinning={lodar}>
{isAuthenticated ? (
<>
<Header type={type} setType={setType} />
<Outlet context={[type, setType]} />
</>
) : (
<Navigate to="/login" />
)}
</Spin>
);
}
export default PrivateRoute;
So what I want to do here is to always redirect the user to the "/payment" after signup. and if the user again comes after login then it will again redirect it to the payment page so for that I am keeping a flag in my database user.step
and checking by api call on the PrivateRoute component.
The issue is it loads the "/dashboard" page before the fetchUser
api call which should not happen and show some lodar before. How can I do that?
Is there any better approach doing this since I always have to make an api call?
Kindly help!!!
Upvotes: 2
Views: 333
Reputation: 203099
Assuming <Spin indicator={antIcon} spinning={lodar}>
is conditionally rendering either a loading spinner/indicator or the wrapped children
then I think the issue is just the initial lodar
state value. It doesn't appear the lodar
state is ever toggled true.
I suggest starting with an initially true
state so the component doesn't immediately render the Outlet
or redirect when the component mounts, prior to any auth checks happening via the useEffect
hook.
Example:
function PrivateRoute({ fetchMe, ...props }) {
const [type, setType] = useState("xxxxx");
const isAuthenticated = localStorage.getItem("authToken");
const navigate = useNavigate();
const [lodar, setLodar] = useState(true); // <-- initially true
useEffect(() => {
setLodar(true); // <-- toggle true when starting async logic
if (isAuthenticated) {
(async () => {
const {
value: { user },
} = await fetchMe();
console.log({ data: user.step1 });
if (user.step === 1) {
navigate("/payment");
}
setLodar(false); // <-- clear loading when complete
})();
}
}, []);
return (
<Spin indicator={antIcon} spinning={lodar}>
{isAuthenticated ? (
<>
<Header type={type} setType={setType} />
<Outlet context={[type, setType]} />
</>
) : (
<Navigate to="/login" />
)}
</Spin>
);
}
Upvotes: 3