Cancel axios requests in a React context provider using refs

Created May 22 2020

JS
1
import axios, { Canceler } from "axios";
2
import * as React from "react";
3
4
const fetchData = async (cancelToken: CancelToken) => {
5
try {
6
const response = await axios.get("http://my-endpoint.com/api/sample", {
7
headers: {
8
"Content-Type": "application/json",
9
},
10
/**
11
* Pass the cancel token in the axios get call
12
*/
13
cancelToken,
14
});
15
16
return response;
17
} catch (error) {
18
throw error;
19
}
20
};
21
22
type DataContextValue = ReturnType<typeof useData>;
23
24
export const DataContext = React.createContext<DataContextValue | undefined>(
25
undefined
26
);
27
28
const useData = () => {
29
const [data, setData] = React.useState<number>(0);
30
31
/**
32
* Create a React ref to store the cancel token
33
*/
34
const cancelDataRequest = React.useRef<Canceler>();
35
const getData = React.useCallback(async () => {
36
/**
37
* If a cancel token is already present: call it to cancel any previous
38
* call of fetchData that is still in progress
39
*/
40
cancelDataRequest.current && cancelDataRequest.current();
41
42
/**
43
* Create a new axios cancel token and assign it the React ref
44
*/
45
const cancelToken = new axios.CancelToken((c) => {
46
cancelDataRequest.current = c;
47
});
48
try {
49
const data = await fetchData(cancelToken);
50
setData(data);
51
} catch (e) {
52
throw e;
53
}
54
return data;
55
}, [data]);
56
57
return {
58
getData,
59
data,
60
};
61
};
62
63
/**
64
* React context provider that will give access to data
65
* and getData to any DataContext consumer
66
*/
67
const DataProvider: React.FC = (props) => {
68
const value = useData();
69
70
return (
71
<DataContext.Provider value={value}>{props.children}</DataContext.Provider>
72
);
73
};