import { useState, useEffect } from "react"; const useFetch = (url) => { const [data, setData] = useState(null); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { const abortController = new AbortController(); const signal = abortController.signal; const fetchData = async () => { try { const response = await fetch(url, { signal }); if (!response.ok) { // Handle non-200 status codes throw new Error("Network response was not ok"); } const jsonData = await response.json(); setData(jsonData); setIsLoading(false); } catch (error) { if (error.name === "AbortError") { console.log("Request aborted"); } else { setError(error.message); setIsLoading(false); } } }; fetchData(); // Cleanup function return () => { // Abort the ongoing request if the component unmounts or if a new request is made abortController.abort(); }; }, [url]); return { data, isLoading, error }; }; export default useFetch;
Usage of useFetch custom React hook:
import React from 'react'; import useFetch from './useFetch'; function MyComponent() { const { data, isLoading, error } = useFetch('https://api.example.com/data'); if (isLoading) { return <div>Loading...</div>; } if (error) { return <div>Error: {error}</div>; } return ( <div> {data && data.map((item) => <div key={item.id}>{item.name}</div>)} </div> ); } export default MyComponent;
// TODO: Add refetch method.