Last active
February 7, 2019 15:00
-
-
Save martinmckenna/51604f98eedaef36432ffe0b99a7eab3 to your computer and use it in GitHub Desktop.
Data Fetching with Hooks and Axios Cancellable Requests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useEffect, useState } from 'react'; | |
import Axios from 'axios' | |
/** | |
* returns an object which contains | |
* both the fetch request | |
* and the function that will cancel the in-flight request | |
*/ | |
const fetchData = () => { | |
const source = Axios.CancelToken.source(); | |
return { | |
request: () => Axios('https://site.com/endpoint', { | |
method: 'GET', | |
cancelToken: source.token | |
}).then(response => response.data), | |
cancel: source.cancel | |
} | |
} | |
/** | |
* intercept all network requests and add a "wasCancelled" | |
* flag if the request was cancelled mid-flight | |
*/ | |
Axios.interceptors.response.use( | |
(response) => response, | |
(err: AxiosError): Promise<APIError[]> => { | |
/** was this a result of an Axios cancel invocation */ | |
const wasCancelled = Axios.isCancel(err); | |
return err.response && !wasCancelled | |
? Promise.reject(err.response) | |
: Promise.reject([ | |
{ | |
reason: 'There was an error', | |
wasCancelled | |
} | |
]); | |
} | |
); | |
const MyComponent = (props: MyProps) => { | |
const [loading, updateLoading] = useState<boolean>(false); | |
const [error, updateError] = useState<APIError[] | undefined >(undefined); | |
const [fetchedData, updateFetchedData] = useState<DataType | undefined>(undefined); | |
useEffect(() => { | |
/** set loading to true, display spinner or whatever */ | |
updateLoading(true); | |
fetchData().request() | |
.then((response) => { | |
updateLoading(false); | |
updateTemplateData(response) | |
}) | |
.catch((err: APIError[]) => { | |
/** | |
* if the request was cancelled mid-flight, early return | |
* the idea is to prevent setting state on unmounted components | |
*/ | |
if(err[0].wasCancelled) { return; } | |
updateLoading(false); | |
updateError(err) | |
}) | |
return () => { | |
/** on unmount, cancel the request if it is in-flight */ | |
fetchData.cancel(); | |
} | |
}, []) | |
... | |
... | |
... | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment