Axios does not support canceling requests at the moment. Please see this issue for details.
UPDATE: Cancellation support was added in axios v0.15.
EDIT: The axios cancel token API is based on the withdrawn cancelable promises proposal.
UPDATE 2022: Starting from v0.22.0 Axios supports AbortController to cancel requests in fetch API way:
Example:
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
Answer from Nick Uraltsev on Stack OverflowAxios does not support canceling requests at the moment. Please see this issue for details.
UPDATE: Cancellation support was added in axios v0.15.
EDIT: The axios cancel token API is based on the withdrawn cancelable promises proposal.
UPDATE 2022: Starting from v0.22.0 Axios supports AbortController to cancel requests in fetch API way:
Example:
const controller = new AbortController();
axios.get('/foo/bar', {
signal: controller.signal
}).then(function(response) {
//...
});
// cancel the request
controller.abort()
Using useEffect hook:
useEffect(() => {
const ourRequest = Axios.CancelToken.source() // <-- 1st step
const fetchPost = async () => {
try {
const response = await Axios.get(`endpointURL`, {
cancelToken: ourRequest.token, // <-- 2nd step
})
console.log(response.data)
setPost(response.data)
setIsLoading(false)
} catch (err) {
console.log('There was a problem or request was cancelled.')
}
}
fetchPost()
return () => {
ourRequest.cancel() // <-- 3rd step
}
}, [])
Note: For POST request, pass cancelToken as 3rd argument
Axios.post(`endpointURL`, {data}, {
cancelToken: ourRequest.token, // 2nd step
})
Cancel Request if a subsequent request is made?
ajax - abort all Axios requests when change route use vue-router - Stack Overflow
How to cancel all prior requests and only display results from the latest API call.
Is it possible to cancel axios requests?
Videos
» npm install axios-cancel
Update: Axios (0.22.0+)
CancelToken is now deprecated. Check @m0r answer for updated solution using AbortController. Here is the link from the official documentation:
https://axios-http.com/docs/cancellation
Original answer
Basically you have to generate a global cancel token
const CancelToken = axios.CancelToken;
const source = CancelToken.source();
and use it in all your requests by passing it in the config parameter
GET request:
axios.get('/user/12345', {
cancelToken: source.token
}).catch(function(thrown) {
if (axios.isCancel(thrown)) {
console.log('Request canceled', thrown.message);
} else {
// handle error
}
});
POST request:
axios.post('/user/12345', {
name: 'new name'
}, {
cancelToken: source.token
})
Then, within a vue-router beforeEach navigation guard you can cancel all requests using:
source.cancel('Operation canceled by the user.');
Here's the official axios guide for cancellation: https://github.com/axios/axios#cancellation
Answer from @fabruex is correct. I just wanted to add here that if you have lot of api calls then you have to pass cancellation token in each api call config. In order to reduce that code, you can create axios instance and add request interceptor which will add that common cancellation token and then you can assign a new value to token when cancellation is done or your route has changed.
// Some global common cancel token source
let cancelSource = axios.CancelToken.source();
// Request interceptor
export const requestInterceptor = config => {
config.cancelToken = cancelSource.token;
return config;
};
// Add request interceptor like this
const request = axios.create({ baseURL: SOME_URL });
request.interceptors.request.use(requestInterceptor);
// Now you can use this axios instance like this
await request.get('/users');
// and
await request.post('/users', data);
// When you will cancel
cancelSource.cancel('Your cancellation message');
// And all the api calls initiated by axios instance which has request interceptor will be cancelled.
Edit to answer @Suneet Jain
You can create a class and create an instance which you can update
class CancelToken {
constructor(initialValue) {
this.source = initialValue;
}
getSource() {
return this.source;
}
setSource(value) {
this.source = value;
}
cancel() {
this.source.cancel();
}
}
export const cancelSource = new CancelToken(axios.CancelToken.source());
You can import that instance cancelSource and call cancel when required e.g. when you logout, you can call to cancel all request which have cancellation token given by cancelSource.getSource()
So after logout
cancelSource.cancel('CANCELLED');
And when again user will login, set new cancellation token to this global instance
cancelSource.setSource(axios.CancelToken.source());
Let's consider a scenario of a website like Amazon in which a user can choose filters. After every filter that is selected or unselected an API call has to be made. If a user selects four filters in a row, four API calls have to be made. We do not want to display the results we received from the first three filters and only want to display those from the last request. How do we implement such functionality?
I have this component with the function getAnswer When user clicks the button, the getAnswer will fetch the question's answer from the backend, sets the fetched answer to local useState, and make another POST request back to the backend.
The problem is I get the good old "cannot reform state update on unmounted component" and "400 request error" when user moves to another page.
next-dev.js?3515:25 Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in a useEffect cleanup function.
This is the error log; how do I cancel ALL axios requests and setState requests inside the getAnswer function when the component is unmounted?
export const SingleQuestion = ({ question }: { question: Question }) => {
const [answer, setAnswer] = useState('');
const [answered, setAnswered] = useState(false);
const [isAnswerLoading, setIsAnswerLoading] = useState(false);
const getAnswer = async () => {
// prevent fetch when user is generating more questions
setIsAnswerLoading(true);
const GPTResponse = await axios.post(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/nlp/questions/`,
{
prompt: question.question,
},
{ withCredentials: true }
);
const parsed = JSON.parse(GPTResponse.data);
setAnswer(parsed.choices[0].text);
setAnswered(true);
await axios.patch(
`${process.env.NEXT_PUBLIC_API_URL}/api/v1/questions/${question.id}/`,
{ answer: parsed.choices[0].text, answered: true },
{ withCredentials: true }
);
setIsAnswerLoading(false);
};
return (
<motion.ul variants={variants} initial="hidden" animate="show">
<button
onClick={getAnswer}
>
Answer Question
<button/>
</motion.ul>
);