What is the correct approach to cancel async requests within a React functional component?
I have a script that requests data from an API on load (or under certain user actions), but if this is in the process of being executed & the user navigates away, it results in the following warning:
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.
Most of what I have read solves this with the AbortController
within the componentDidUnmount
method of a class-based component. Whereas, I have a functional component in my React app which uses Axois to make an asynchronous request to an API for data.
The function resides within a useEffect
hook in the functional component to ensure that the function is run when the component renders:
useEffect(() => {
loadFields();
}, [loadFields]);
This is the function it calls:
const loadFields = useCallback(async () => {
setIsLoading(true);
try {
await fetchFields(
fieldsDispatch,
user.client.id,
user.token,
user.client.directory
);
setVisibility(settingsDispatch, user.client.id, user.settings);
setIsLoading(false);
} catch (error) {
setIsLoading(false);
}
}, [
fieldsDispatch,
user.client.id,
user.token,
user.client.directory,
settingsDispatch,
user.settings,
]);
And this is the axios request that is triggered:
async function fetchFields(dispatch, clientId, token, folder) {
try {
const response = await api.get(clientId + "/fields", {
headers: { Authorization: "Bearer " + token },
});
// do something with the response
} catch (e) {
handleRequestError(e, "Failed fetching fields: ");
}
}
Note: the api
variable is a reference to an axios.create
object.