OiO.lk Community platform!

Oio.lk is an excellent forum for developers, providing a wide range of resources, discussions, and support for those in the developer community. Join oio.lk today to connect with like-minded professionals, share insights, and stay updated on the latest trends and technologies in the development field.
  You need to log in or register to access the solved answers to this problem.
  • You have reached the maximum number of guest views allowed
  • Please register below to remove this limitation

interceptors when pages refreshes

  • Thread starter Thread starter Ahcene Tayebi
  • Start date Start date
A

Ahcene Tayebi

Guest
My refresh scenario works fine, but i only call the interceptor when the user changes so after i login, but when i refresh the page the userRef will be empty and also the interceptor won't be called

i've tried a use effect on mount when the token is available on my local storage but it still didn't work for me

Code:
import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { jwtDecode } from "jwt-decode";

const Login = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [errorMessage, setErrorMessage] = useState("");
  const [successMessage, setSuccessMessage] = useState("");
  const userRef = useRef(null);
  const navigate = useNavigate();

  useEffect(() => {
    if (userRef.current) {
      setupAxiosInterceptors();
    }
  }, [userRef.current]);

  //Login Handler
  const handleLogin = async (e) => {
    e.preventDefault();
    try {
      const response = await axios.post("http://localhost:5000/api/login", {
        email,
        password,
      });

      const { accessToken, refreshToken } = response.data;
      localStorage.setItem("token", accessToken);

      const decodedUser = jwtDecode(accessToken);
      userRef.current = { ...decodedUser, refreshToken };
      console.log("user refresh Token: ", userRef.current.refreshToken);

      setErrorMessage("");
      setSuccessMessage("Logged in successfully.");

      setTimeout(() => {
        navigate("/dashboard");
      }, 500);
    } catch (error) {
      if (
        error.response &&
        (error.response.status === 400 || error.response.status === 500)
      ) {
        setErrorMessage("Credentials not correct. Please try again.");
        setSuccessMessage("");
      } else {
        console.error("Login error:", error);
        setErrorMessage("Failed to log in. Please try again later.");
        setSuccessMessage("");
      }
    }
  };

  //Generate a new token
  const refreshAccessToken = async () => {
    try {
      if (!userRef.current || !userRef.current.refreshToken) {
        throw new Error("Refresh token not available");
      }

      const response = await axios.post(
        "http://localhost:5000/api/refresh-token",
        { token: userRef.current.refreshToken }
      );
      const newAccessToken = response.data.accessToken;
      localStorage.setItem("token", newAccessToken);
      console.log("New access token set ... ");
      return newAccessToken;
    } catch (error) {
      console.log(error);
    }
  };

  // axios interceptor
  const setupAxiosInterceptors = () => {
    axios.interceptors.request.use(
      async (config) => {
        let token = localStorage.getItem("token");
        if (!token) {
          throw new Error("Token is not available");
        }
        const decodedToken = jwtDecode(token);
        const tokenExpiry = decodedToken.exp * 1000;
        const currentDate = new Date().getTime();
        // Compare token expiry with current time
        setTimeout(async () => {
          if (tokenExpiry - 5000 < currentDate) {
            token = await refreshAccessToken();
            console.log("New token:", token);
            config.headers["Authorization"] = `Bearer ${token}`;
            console.log("Token refreshed successfully");
          }
        }, 1000);

        return config;
      },
      (error) => {
        return Promise.reject(error);
      }
    );
  };
  return (
    <div className="text-center">
      <form
        onSubmit={handleLogin}
        className="flex flex-col gap-4 items-center *:w-[300px] *:rounded-md *:border-2 *:border-solid *:border-green-600 *:indent-2 *:text-black mt-10"
      >
        <input
          type="email"
          name="email"
          placeholder="Email"
          value={email}
          onChange={(e) => setEmail(e.target.value)}
          required
        />
        <input
          type="password"
          name="password"
          placeholder="Password"
          value={password}
          onChange={(e) => setPassword(e.target.value)}
          required
        />
        <input
          type="submit"
          value="Login"
          className="bg-red-500 border-none font-bold"
        />
      </form>
      {errorMessage && <span className="text-red-700">{errorMessage}</span>}
      {successMessage && (
        <span className="text-green-700">{successMessage}</span>
      )}
    </div>
  );
};

export default Login;

<p>My refresh scenario works fine, but i only call the interceptor when the user changes so after i login, but when i refresh the page the userRef will be empty and also the interceptor won't be called</p>
<p>i've tried a use effect on mount when the token is available on my local storage but it still didn't work for me</p>
<pre><code>import React, { useState, useEffect, useRef } from "react";
import axios from "axios";
import { useNavigate } from "react-router-dom";
import { jwtDecode } from "jwt-decode";

const Login = () => {
const [email, setEmail] = useState("");
const [password, setPassword] = useState("");
const [errorMessage, setErrorMessage] = useState("");
const [successMessage, setSuccessMessage] = useState("");
const userRef = useRef(null);
const navigate = useNavigate();

useEffect(() => {
if (userRef.current) {
setupAxiosInterceptors();
}
}, [userRef.current]);

//Login Handler
const handleLogin = async (e) => {
e.preventDefault();
try {
const response = await axios.post("http://localhost:5000/api/login", {
email,
password,
});

const { accessToken, refreshToken } = response.data;
localStorage.setItem("token", accessToken);

const decodedUser = jwtDecode(accessToken);
userRef.current = { ...decodedUser, refreshToken };
console.log("user refresh Token: ", userRef.current.refreshToken);

setErrorMessage("");
setSuccessMessage("Logged in successfully.");

setTimeout(() => {
navigate("/dashboard");
}, 500);
} catch (error) {
if (
error.response &&
(error.response.status === 400 || error.response.status === 500)
) {
setErrorMessage("Credentials not correct. Please try again.");
setSuccessMessage("");
} else {
console.error("Login error:", error);
setErrorMessage("Failed to log in. Please try again later.");
setSuccessMessage("");
}
}
};

//Generate a new token
const refreshAccessToken = async () => {
try {
if (!userRef.current || !userRef.current.refreshToken) {
throw new Error("Refresh token not available");
}

const response = await axios.post(
"http://localhost:5000/api/refresh-token",
{ token: userRef.current.refreshToken }
);
const newAccessToken = response.data.accessToken;
localStorage.setItem("token", newAccessToken);
console.log("New access token set ... ");
return newAccessToken;
} catch (error) {
console.log(error);
}
};

// axios interceptor
const setupAxiosInterceptors = () => {
axios.interceptors.request.use(
async (config) => {
let token = localStorage.getItem("token");
if (!token) {
throw new Error("Token is not available");
}
const decodedToken = jwtDecode(token);
const tokenExpiry = decodedToken.exp * 1000;
const currentDate = new Date().getTime();
// Compare token expiry with current time
setTimeout(async () => {
if (tokenExpiry - 5000 < currentDate) {
token = await refreshAccessToken();
console.log("New token:", token);
config.headers["Authorization"] = `Bearer ${token}`;
console.log("Token refreshed successfully");
}
}, 1000);

return config;
},
(error) => {
return Promise.reject(error);
}
);
};
return (
<div className="text-center">
<form
onSubmit={handleLogin}
className="flex flex-col gap-4 items-center *:w-[300px] *:rounded-md *:border-2 *:border-solid *:border-green-600 *:indent-2 *:text-black mt-10"
>
<input
type="email"
name="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<input
type="password"
name="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<input
type="submit"
value="Login"
className="bg-red-500 border-none font-bold"
/>
</form>
{errorMessage && <span className="text-red-700">{errorMessage}</span>}
{successMessage && (
<span className="text-green-700">{successMessage}</span>
)}
</div>
);
};

export default Login;

</code></pre>
 

Latest posts

Online statistics

Members online
0
Guests online
4
Total visitors
4
Top