1

I created a separate node.js restful API for checking if the user token is valid. I did this for my react protected routes, even though most of my endpoints already checks the user token.

My redux Thunk:

const verifyToken = () => {
  return async (dispatch: Dispatch) => {
    await axios
      .get("http://localhost:9999/authenticate", {
        headers: { Authorization: `Bearer ${localStorage.getItem("token")}` },
      })
      .then(async (resp) => {
        const { message } = await resp.data;
        console.log(message);
        if (message === "verified") dispatch({ type: "signIn-success" });
      })
      .catch((err) => {
        console.log(err);
        dispatch({ type: "logout-user" });
      });
  };
};

Protected Route:

const ProtectedRoute: FC<{ children: ReactNode; path: string }> = ({
  children,
  path,
}) => {
  const dispatch = useDispatch(); 
  dispatch(verifyToken()); //dispatch thunk
  const status = useSelector((store: RootStore) => store.status)

  return status && status === "loggedOut" ? (
    <Redirect to="/" />
  ) : (
    <Route path={path} render={() => <>{children}</>} />
  );
};

The problem is that it takes time to dispatch my thunk, so it redirects to "/" even though the user token checking hasn't finished.

So what happens is, the value of status is "loggedOut" at first then my thunk will check if the token is valid. If it is, status becomes "loggedIn", but its too late because it already redirected to "/"

1
  • 2
    You should add a "pending" or "processing" state and conditionally not render the route or redirect until the updated status is known. Commented Jan 4, 2021 at 3:39

1 Answer 1

1

You need a loading for the time you're dispatching the action, something like this:


const ProtectedRoute: FC<{ children: ReactNode, path: string }> = ({
  children,
  path,
}) => {
  const [loading, setLoading] = useState(true);

  const dispatch = useDispatch();
  const status = useSelector((store: RootStore) => store.status);

  async function verify() {
    await dispatch(verifyToken()); //dispatch thunk
    setLoading(false);
  }

  useEffect(() => {
    verify();
  }, []);

  if (loading) return <div>Show Loading...</div>;

return status === "loggedOut" ? (
  <Redirect to="/" />
) : (
  <Route path={path} render={() => <>{children}</>} />
);
};
Sign up to request clarification or add additional context in comments.

1 Comment

It worked but I also needed to add "await" on my thunk. "await axios()"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.