Profer
Profer

Reputation: 643

Redirect to dashboard after successful payment

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

Answers (1)

Drew Reese
Drew Reese

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

Related Questions