I guess it doesn't work because you are trying to cancel the wrong token.
Let's look at this example:
export default function Home() {
let axiosCancelToken;
async function getData() {
if (axiosCancelToken) {
axiosCancelToken.cancel();
}
axiosCancelToken = axios.CancelToken.source();
let val = await axios({
method: "GET",
url: "https://jsonplaceholder.typicode.com/todos/1",
cancelToken: axiosCancelToken.token
});
}
return (
<div>
<button onClick={getData}>Get Data</button>
</div>
);
}
Try clicking the button twice quickly, you will see the first request canceled as expected.
But if I change the code by adding some React state, it won't work anymore:
export default function App() {
let axiosCancelToken;
let [count, setCount] = useState(0);
async function getData() {
setCount((count) => count + 1);
if (axiosCancelToken) {
axiosCancelToken.cancel();
console.warn("request cancelled");
}
axiosCancelToken = axios.CancelToken.source();
let val = await axios({
method: "GET",
url: "https://jsonplaceholder.typicode.com/todos/1",
cancelToken: axiosCancelToken.token
});
}
return (
<div>
<button onClick={getData}>Get Data {count}</button>
</div>
);
}
And the reason for that is that when React has to re-render, it will call your function component again, where your axiosCancelToken will be instantiated again in the new scope.
To solve this you can just use React Refs.
let axiosCancelToken = useRef();
reactjs - how to cancel/abort ajax request in axios - Stack Overflow
Cancel axios get request when typing reactjs - Stack Overflow
Axios Post Request not firing with cancelToken
Cant cancel Axios post request via CancelToken
Videos
» npm install react-use-cancel-token
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()
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
})
Since axios v0.15 you can cancel request:
You can also create a cancel token by passing an executor function to the CancelToken constructor:
var CancelToken = axios.CancelToken;
var cancel;
axios.get('/user/12345', {
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
})
});
// cancel the request
cancel();
For more information please have a look Cancellation. And according to your code:
import React from 'react'
import axios from 'axios';
export function autocompleteSearchTest(value) {
if (cancel != undefined) {
cancel();
}
return axios.get(`https://jqueryui.com/resources/demos/autocomplete/search.php`, {
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
}),
params: {
q: value
}
})
.then(response => {
return response.data.response;
})
.catch(error => {
const result = error.response;
return Promise.reject(result);
});
}
var CancelToken = axios.CancelToken;
var cancel;
export class AutoComplete extends React.Component {
constructor() {
super()
this.state = {
search: ''
};
this.handleSearchChange = this.handleSearchChange.bind(this);
}
handleSearchChange(event) {
const target = event.target;
const value = target.value;
this.setState({
search: value
});
autocompleteSearchTest(value)
}
render() {
return (
<div className="App-intro Dialog-section">
<h2>AutoComplete</h2>
<div className="form-control">
<label htmlFor="password">Lookup :</label>
<input name="search" type="text" value={this.state.search}
onChange={this.handleSearchChange}
id="password" ref="password" placeholder="Enter line"/>
</div>
</div>
)
}
}
export default AutoComplete;
And here it's

use: react, axios and redux-axios-middleware
user actions:
import axios from 'axios';
import * as type from 'constants/user';
const CancelToken = axios.CancelToken;
let cancel;
export const addUser = (data) => {
if (cancel !== undefined) cancel();
return ({
types: [type.ADD_USER_REQUEST, type.ADD_USER_SUCCESS, type.ADD_USER_FAILURE],
payload: {
request: {
url: '/api/user',
cancelToken: new CancelToken(c => cancel = c),
method: 'POST',
data,
},
},
});
};
I have found out that you can cancel post request this way,i missunderstand this documentation part. In previous code,i have passed cancelToken to the POST data request not as a axios setting.
import axios from 'axios'
var CancelToken = axios.CancelToken;
var cancel;
axios({
method: 'post',
url: '/test',
data: {
firstName: 'Fred',
lastName: 'Flintstone'
},
cancelToken: new CancelToken(function executor(c) {
// An executor function receives a cancel function as a parameter
cancel = c;
})
}).then(()=>console.log('success')).catch(function(err){
if(axios.isCancel(err)){
console.log('im canceled');
}
else{
console.log('im server response error');
}
});
// this cancel the request
cancel()
Cancel previous Axios request on new request with cancelToken and source.
https://github.com/axios/axios#cancellation
// cancelToken and source declaration
const CancelToken = axios.CancelToken;
let source = CancelToken.source();
source && source.cancel('Operation canceled due to new request.');
// save the new request for cancellation
source = axios.CancelToken.source();
axios.post(url, postData, {
cancelToken: source.token
})
.then((response)=>{
return response && response.data;
})
.catch((error)=>{
return error;
});
Based on the Axios Documentation - Interceptors, the interceptor function should return the req.
API.interceptors.request.use((req) => {
if(localStorage.getItem('profile')) {
req.headers.Authorization = `Bearer ${JSON.parse(localStorage.getItem('profile')).token}`;
}
return req;
})
My 2cents: looks like it's easier NOT to make the request in the first place, if user is not authorized =) Just add a global middleware on frontend to redirect user to auth page. Here is an example in Vue, but you get the logic.
import { Middleware } from '@nuxt/types';
import { RoutesName } from '~/shared/repository/routes/routes-name';
const auth: Middleware = async (context) => {
const { route, store } = context;
const isAuthorized = store.getters['user/isAuthorized'];
const isAuthPage = route.name === RoutesName.auth;
if (!isAuthorized && !isAuthPage) {
return context.redirect(`/${RoutesName.auth}`);
}
if (isAuthorized && isAuthPage) {
return context.redirect('/');
}
};
export default auth;