How to fetch data with a custom hook in React
Fetching data efficiently while managing loading and error states is a core requirement in modern React applications. As the creator of CoreUI, a widely used open-source UI library, and with over 11 years of experience in software development, I’ve built countless data-driven interfaces where reusable data fetching logic is essential. The most effective approach is creating a custom hook that encapsulates all data fetching logic, including loading states and error handling. This pattern promotes code reusability and maintains clean component separation.
Create a custom hook that handles data fetching with built-in loading and error states for maximum reusability.
function useFetch(url) {
  const [data, setData] = useState(null)
  const [loading, setLoading] = useState(true)
  const [error, setError] = useState(null)
  useEffect(() => {
    fetch(url)
      .then(response => response.json())
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false))
  }, [url])
  return { data, loading, error }
}
This custom hook encapsulates all data fetching logic using React’s built-in hooks. The useState hooks manage the data, loading state, and any errors that occur. The useEffect hook triggers the fetch when the URL changes and handles the complete request lifecycle. The hook returns an object containing all three states, making it easy to destructure in components and handle different UI states appropriately.
Best Practice Note:
This is the same pattern we use in CoreUI React components for consistent data management. Consider adding cleanup logic with AbortController for component unmounting and implementing retry mechanisms for production applications.



