Проблема с перехватчиком Axios реагирует на Redux и Node

Я создал собственный хук и создал в нем экземпляр axios для получения новых токенов всякий раз, когда истекает срок действия токена доступа. Первоначально при загрузке страницы с токеном все в порядке, но после истечения времени ожидания мой токен не устанавливается, что не так в моем коде .

Это мой файл useAxiosInstance.js.

import axios from "axios";
import { jwtDecode } from "jwt-decode";
import { useDispatch } from "react-redux";
import { authSuccess } from "../redux/auth/authSlice";
let userData = localStorage.getItem("userData")
  ? JSON.parse(localStorage.getItem("userData"))
  : null;
export const axiosInstance = axios.create({
  baseURL: process.env.REACT_APP_API_URL,
  headers: {
    Authorization: userData?.accessToken
      ? `Bearer ${userData.accessToken}`
      : "",
  },
});

const useAxiosInstance = () => {
  const getTokens = async (data) => {
    try {
      const res = await axios.post(
        `${process.env.REACT_APP_API_URL}refresh`,
        data,
        {
          headers: {
            "Content-Type": "application/json",
          },
        }
      );
      return res.data;
    } catch (err) {
      return err;
    }
  };

  axiosInstance.interceptors.request.use(
    async (config) => {
      const accessTokenExpiryDate = jwtDecode(userData?.accessToken);

      console.info(accessTokenExpiryDate,"ex")

      if (accessTokenExpiryDate.exp * 1000 < new Date().getTime()) {
        const { accessToken, refreshToken } = await getTokens(
          JSON.stringify({ token: userData.refreshToken })
        );

        userData = {
          ...userData,
          accessToken,
          refreshToken,
        };
        localStorage.setItem("userData", JSON.stringify(userData));
        config.headers["Authorization"] = "Bearer " + accessToken;
      }
      return config;
    },
    (error) => Promise.reject(error)
  );

  return userData;
};

export default useAxiosInstance;

Это мой файл app.js

import { useDispatch, useSelector } from "react-redux";
import "./app.less";
import Header from "./components/header/Header";
import { BrowserRouter } from "react-router-dom";
import { ToastContainer } from "react-toastify";
import "react-toastify/dist/ReactToastify.css";
import { useEffect } from "react";
import { authSuccess } from "./redux/auth/authSlice";
import AppRoute from "./routes/AppRoute";
import useAxiosInstance from "./utilities/useAxiosInstance"

function App() {
  const theme = useSelector((state) => state.theme);
  const auth = useSelector((state) => state.auth);
  const dispatch = useDispatch();

  const userData = useAxiosInstance();

  useEffect(() => {
    dispatch(authSuccess(userData));
  }, [userData, dispatch]);


  return (
    <BrowserRouter>
      <div
        className = {theme.mode === "dark" ? "dark-mode app" : "light-mode app"}
      >
        {auth?.data && <Header />}
        <ToastContainer />
        <AppRoute />
      </div>
    </BrowserRouter>
  );
}

export default App;

Это мой файл фрагмента аутентификации

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  data: null,
};

const authSlice = createSlice({
  name: "auth",
  initialState,
  reducers: {
    authSuccess: (state, action) => {
      state.data =action.payload
    },
    authLogout: (state, action) => {
      state.data = null;
    },
  },
});

export const { authSuccess, authLogout } = authSlice.actions;

export default authSlice.reducer;

это мой файл пользовательского фрагмента

import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
import { showToast } from "../../utilities/toast";
import { authLogout } from "../auth/authSlice";
import { axiosInstance } from "../../utilities/useAxiosInstance";



const initialState = {
  update: { loading: false, data: null, error: null },
  get: { loading: false, data: null, error: null },
  delete: { loading: false, data: null, error: null },
};

export const getUser = createAsyncThunk("user/getUser", (payload) => {
  const { data, mode } = payload;
  return axiosInstance
    .get(`/user/${data?._id}`, {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + data.accessToken,
      },
    })
    .then((res) => res.data)
    .catch((error) => {
      showToast(error.response.data.message, mode, "error");
      throw error.response.data.message;
    });
});

export const deleteUser = createAsyncThunk("user/deleteUser", (payload) => {
  const { auth, navigate, mode, dispatch } = payload;

  return axiosInstance
    .delete(`/user/${auth._id}`, {
      headers: {
        "Content-Type": "application/json",
        Authorization: "Bearer " + auth.accessToken,
      },
    })
    .then((res) => {
      showToast("Deleted Successfully!", mode, "success");
      dispatch(authLogout());
      localStorage.removeItem("userData");
      navigate("/");
    })
    .catch((err) => {
      showToast(err?.response?.data?.message, mode, "error");
      throw err.response.data.message;
    });
});

export const editUser = createAsyncThunk("user/editUser", (payload) => {
  const { form, data, mode } = payload;

  return axiosInstance
    .put(`/user/${data._id}`, form, {
      headers: {
        "Content-Type": "multipart/form-data",
        // Authorization: "Bearer " + data.accessToken,
      },
    })
    .then((res) => {
      showToast("Updated Successfully!", mode, "success");
    })
    .catch((err) => {
      showToast(err?.response?.data?.message, mode, "error");
      throw err.response.data.message;
    });
});

const userSlice = createSlice({
  name: "user",
  initialState,
  extraReducers: (builder) => {
    builder.addCase(getUser.pending, (state, action) => {
      state.get.loading = true;
    });
    builder.addCase(getUser.fulfilled, (state, action) => {
      state.get.loading = false;
      state.get.data = action.payload;
    });
    builder.addCase(getUser.rejected, (state, action) => {
      state.get.loading = false;
      state.get.error = action.payload;
    });
    builder.addCase(editUser.pending, (state, action) => {
      state.update.loading = true;
    });
    builder.addCase(editUser.fulfilled, (state, action) => {
      state.update.loading = false;
      state.update.data = action.payload;
    });
    builder.addCase(editUser.rejected, (state, action) => {
      state.update.loading = false;
      state.update.error = action.payload;
    });
    builder.addCase(deleteUser.pending, (state, action) => {
      state.delete.loading = true;
    });
    builder.addCase(deleteUser.fulfilled, (state, action) => {
      state.delete.loading = false;
      state.delete.data = action.payload;
    });
    builder.addCase(deleteUser.rejected, (state, action) => {
      state.delete.loading = false;
      state.delete.error = action.payload;
    });
  },
});

export default userSlice.reducer;

поскольку я вызываю getUser api при загрузке страницы, он вызывает пользовательский крючок, но для редактирования и удаления только до тех пор, пока токен доступа не существует, он работает, а в остальное время мой новый токен не обновляется

🤔 А знаете ли вы, что...
JavaScript поддерживает работу с различными форматами данных, такими как JSON и XML.


52