1

I am trying to implement a redirect to login when the user lands on a restricted page.

I followed the instructions on When user is not logged in redirect to login. Reactjs, and added my async auth function (checkLoggedIn), which returns either true or false after making an api call to my database.

However, it seems like the render function below always run BEFORE checkLoggedIn finishes. Thus the assignment of boolean variable "isLoggedin" is always true in the final ternary operator, even when "checkLoggedIn()" returns false when finished.

So no matter the user is actually logged in or not, it will always render the supposedly protected pages.

I am still new to React, and familiar with Redux and Context if that helps.

Thank you,

function PrivateRoute({ children, ...rest }) {
  let landingPath = useLocation();

  const checkLoggedIn = async () => {

    let token = localStorage.getItem("auth-token");

    if (token === null) {
      localStorage.setItem("auth-token", "");
      token = "";
    }

    const tokenRes = await Axios.post(
      "http://localhost:5000/users/tokenIsValid",
      null,
      { headers: { "x-auth-token": token } }
    );

    if (tokenRes.data) {

        const userRes = await Axios.get("http://localhost:5000/users/", {
        headers: { "x-auth-token": token },
      });

      return true;
    }
    return false;
  };

  let isLoggedin = checkLoggedIn();

  return (
    <Route
      {...rest}
      render={() =>
        isLoggedin ? (
          children
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: landingPath.pathname },
            }}
          />
        )
      }
    />
  );
}
Sean
  • 508
  • 6
  • 20

1 Answers1

1
  1. Use a state to know whether the user is logged in or not.
  2. Update your state accordingly in useEffect to make sure the user is logged in or not.
  3. Redirect accordingly with respect to your state.
STATE
  • isLoggedIn -> null -> haven't fetched yet.
  • isLoggedIn -> true -> yes, user is logged in.
  • isLoggedIn -> false -> nope, user is not logged in. redirect.
function PrivateRoute({ children, ...rest }) {
  const [isLoggedIn, setIsLoggedIn] = React.useState(null);
  const landingPath = useLocation();

  React.useEffect(() => {
    async function checkLoggedIn() {
      const token = localStorage.getItem("auth-token");

      if (token === null) {
        localStorage.setItem("auth-token", "");
        token = "";
      }

      const tokenRes = await Axios.post(
        "http://localhost:5000/users/tokenIsValid",
        null,
        { headers: { "x-auth-token": token } }
      );

      if (tokenRes.data) {
          const userRes = await Axios.get("http://localhost:5000/users/", {
          headers: { "x-auth-token": token },
        });

        setIsLoggedIn(true);
      } else {
        setIsLoggedIn(false);
      }
    }
  }, [])

  if (isLoggedIn === null) return null;

  return (
    <Route
      {...rest}
      render={() =>
        isLoggedin ? (
          children
        ) : (
          <Redirect
            to={{
              pathname: "/login",
              state: { from: landingPath.pathname },
            }}
          />
        )
      }
    />
  );
}
Prateek Thapa
  • 4,829
  • 1
  • 9
  • 23