skip to Main Content

Alright guys, so I have a login token (JWT) returned from an API login endpoint which will expire after 3 hours.

I’m able to save this login token as a cookie after successful login from my auth page. However, the problem now is, how will I re-validate this token to make sure it’s still valid after the user visits the dashboard and then send the user back to the login page?

I tried using an Outlet from react-router-dom, it works, but since I’m fetching data with Axios asynchronously. any better idea will be appreciated.

Here is my PrivateAuth code with the Outlet

import React from "react";
import axios from "../../api/authAxios";
import { Navigate, Outlet } from "react-router-dom";
import { useState } from "react";

export default (PrivateAuth) => {
  const [isLogin, setLogin] = useState(false);
  const user = async () => {
    try {
      const resp = await axios.get("/user");
      if (resp.data.data.user_type === `${process.env.REACT_APP_DISALLOW}`)
        return setLogin(false);

      if (resp.data.status !== false) setLogin(true);

      console.log(resp.data);

      return setLogin(true);
    } catch (error) {
      console.error(error.response.data);
      return setLogin(false);
      <Navigate to="/login" />;
    }
  };

  user();

  return isLogin ? <Outlet /> : <Navigate to="/auth-login" />;
};

2

Answers


  1. Here’s my solution

    import axios from 'axios';
    
    const api = axios.create({
      baseURL: 'https://your-api-url.com',
    });
    
    api.interceptors.request.use(
      async (config) => {
        const token = localStorage.getItem('token');
        if (token) {
          const decodedToken = jwt.decode(token);
    
          // check if token is expired
          if (decodedToken.exp * 1000 < Date.now()) {
            // if token is expired, redirect to login page
            window.location.href = '/login';
            return;
          }
    
          // set the token in the request headers
          config.headers.Authorization = `Bearer ${token}`;
        }
        return config;
      },
      (error) => Promise.reject(error)
    );
    
    export default api;
    
    Login or Signup to reply.
  2. Using useEffect: Instead of calling the user function directly inside the component body, you can use the useEffect hook to fetch the user data when the component mounts. This will ensure that the data is fetched only once, and it won’t cause any rendering issues.

    Handling async/await properly: The user function should return a Promise so that it can be properly awaited inside the useEffect hook. Additionally, the component won’t work as expected if it’s placed inside a function that doesn’t render it.

    import React, { useEffect, useState } from "react";
    import axios from "../../api/authAxios";
    import { useNavigate, Outlet } from "react-router-dom";
    
    export default function PrivateAuth() {
      const [isLogin, setLogin] = useState(false);
      const navigate = useNavigate();
    
      useEffect(() => {
        const user = async () => {
          try {
            const resp = await axios.get("/user");
            if (resp.data.data.user_type === `${process.env.REACT_APP_DISALLOW}`) {
              setLogin(false);
              navigate("/auth-login"); // Redirect to login page if user_type is disallowed
            } else if (resp.data.status !== false) {
              setLogin(true);
            } else {
              setLogin(false);
              navigate("/auth-login"); // Redirect to login page for any other errors
            }
          } catch (error) {
            console.error(error.response.data);
            setLogin(false);
            navigate("/auth-login"); // Redirect to login page if an error occurs during API call
          }
        };
    
        user();
      }, [navigate]);
    
      return isLogin ? <Outlet /> : null; // Show the Outlet when the user is logged in
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search