I have this a Dashboard
component which makes three API calls to fetch widget data.
If any API call fails it refreshes token.
But, when Dashboard
renders it makes API call individually and they don't wait to check if first api call failed or token is refreshed. Each api call ends up making another call to refresh the token.
It should stop at first API call fail and refresh the token.
But it does so for each request. How can I prevent this behaviour.
It seems I need to make request sequentially.
const Dashboard = () => {
const { response: studentResponse } = useAxios(ApiConfig.STUDENT.GET_STUDENTS);
const { response: courseResponse } = useAxios(ApiConfig.COURSE.GET_COURSES);
const { response: feesResponse } = useAxios(ApiConfig.FEES.GET_TOTAL);
return (
<Box padding={2} width="100%">
<Stack direction={'row'} justifyContent="space-between" gap={2} mb={10}>
<NewWidget type={'student'} counter={studentResponse?.data?.length} />
<NewWidget type={'course'} counter={courseResponse?.data?.length} />
<NewWidget type={'earning'} counter={feesResponse?.data} />
</Stack>
</Box>
);
};
export default Dashboard;
use-axios.js
import { useState, useEffect } from 'react';
import axios from 'axios';
import history from '../utils/history';
import refreshToken from './refresh-token';
const Client = axios.create();
Client.defaults.baseURL = 'http://localhost:3000/api/v1';
const getUser = () => {
const user = localStorage.getItem('user');
return user ? JSON.parse(user) : null;
};
const updateLocalStorageAccessToken = (accessToken) => {
const user = getUser();
user.accessToken = accessToken;
localStorage.setItem('user', JSON.stringify(user));
};
Client.interceptors.request.use(
(config) => {
const user = getUser();
config.headers.Authorization = user?.accessToken;
return config;
},
(error) =>
// Do something with request error
Promise.reject(error)
);
Client.interceptors.response.use(
(response) => response,
(error) => {
// Reject promise if usual error
if (error.response.status !== 401) {
return Promise.reject(error);
}
const user = getUser();
const status = error.response ? error.response.status : null;
const originalRequest = error.config;
console.log(originalRequest);
if (status === 401 && originalRequest.url !== '/auth/refresh-token') {
refreshToken(user.refreshToken)
.then((res) => {
const { accessToken } = res.data.data;
Client.defaults.headers.common.Authorization = accessToken;
// update local storage
updateLocalStorageAccessToken(accessToken);
return Client(originalRequest);
})
.catch((err) => {
console.log(err);
if (err.response.status === 401) {
localStorage.setItem('user', null);
history.push('/login');
}
return Promise.reject(err);
});
}
history.push('/login');
return Promise.reject(error);
}
);
export const useAxios = (axiosParams, isAuto = true) => {
const [response, setResponse] = useState(undefined);
const [error, setError] = useState('');
const [loading, setLoading] = useState(true);
const fetchData = async (params) => {
try {
const result = await Client.request({
...params,
method: params.method || 'GET',
headers: {
accept: 'application/json',
},
});
setResponse(result.data);
} catch (error) {
setError(error);
} finally {
setLoading(false);
}
};
useEffect(() => {
if (isAuto) fetchData(axiosParams);
}, [axiosParams, isAuto]); // execute once only
return { fetch: () => fetchData(axiosParams), response, error, loading };
};