I'm using a Custom useHttp hook to fetch some data from api, the problem is that I want to abort the fetching operation when the user navigates to another page and prevent weird errors.
for this I'm using AbortController API inside my hook and whenever the component unmounts the function will be fired.
but when my component renders, I will get an error that tells me the operation was aborted!
Hook Code :
import { useEffect , useState , useCallback , useRef } from 'react';
export const useHttpClient = () => {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState();
const activeHttpRequests = useRef([]);
const sendRequest = useCallback(async (URL, method = 'GET', body = null, headers = {}) => {
setIsLoading(true);
const httpAbortController = new AbortController();
activeHttpRequests.current.push(httpAbortController);
try {
const res = await fetch(URL, {method, body, headers, signal: httpAbortController.signal});
const resData = await res.json();
activeHttpRequests.current = activeHttpRequests.current.filter(reqCtrl => reqCtrl !== httpAbortController)
console.log(activeHttpRequests)
if(!res.ok) {
throw new Error(resData.error);
}
setIsLoading(false)
return resData;
} catch (error) {
setIsLoading(false)
setError(error.message)
throw error;
}
}, [])
const clearError = () => {
setError(null);
}
useEffect(() => {
return () => {
activeHttpRequests.current.forEach(abortCtrl => abortCtrl.abort());
};
}, []);
return {isLoading, error, clearError, sendRequest}
}
and this is the code inside my component :
// Modules
import React, { useEffect, useState } from 'react';
// Hooks
import { useHttpClient } from '../../../helpers/hooks/http-hook';
// Components
import UserList from '../components/user-list/user-list.component';
import ErrorModal from '../../shared/error-modal/error-modal.component';
import Spinner from '../../shared/loading-spinner/spinner.component';
const Users = () => {
const { isLoading , error , clearError , sendRequest } = useHttpClient();
const [loadedUsers, setLoadedUsers] = useState();
useEffect(() => {
const fetchUsers = async () => {
try {
const URL = 'http://localhost:5000/api/users';
const res = await sendRequest(URL);
setLoadedUsers(res.users);
} catch (error) {}
}
fetchUsers();
}, [sendRequest])
return (
<React.Fragment>
<ErrorModal error={error} onClear={clearError} />
{ isLoading && <Spinner overlay/> }
{ !isLoading && loadedUsers && <UserList users={loadedUsers} /> }
</React.Fragment>
);
}
export default Users;