CodeBlanks Logo Icon CodeBlanks

useFetch

Write a useFetch hook that manages data fetching and loading state.

useFetch

useFetch is a hook that fetches data from a URL and returns data, loading, and error states. It collects repeated fetch logic in one place.

It uses three states: useState(null) for data, useState(true) for loading, useState(null) for error. Inside useEffect, fetch(url) is called; the returned promise is handled with .then and .catch.

Cleanup matters: if the component unmounts, the fetch is aborted with AbortController. Otherwise the state update hits a stale component and React warns. We use a simple cancelled flag here.

Cleanup flag

Updating state after a component unmounts warns in React. To prevent this, a let cancelled = false; flag is used; the cleanup function sets cancelled = true.

When the promise resolves, if (!cancelled) setData(...) only updates still-mounted components. This pattern is React's recommended approach for async work.

For advanced cases, AbortController cleanly aborts the fetch. But for simple apps, the cancelled flag is enough and clear.

Practice useFetch skeleton

Complete the skeleton. Write a useFetch(url) hook. Define three states: data (null), loading (true), error (null). Inside useEffect, add let cancelled = false; flag, call fetch(url).then(r => r.json()).then(d => { if (!cancelled) { setData(d); setLoading(false); } }).catch(e => { if (!cancelled) { setError(e); setLoading(false); } }). Cleanup: () => { cancelled = true; }. Dependency [url]. Return [data, loading, error]. Export the hook.

Starter code

App.jsx
import { useState, useEffect } from "react";

// Write the useFetch hook here

Sample solution

App.jsx
import { useState, useEffect } from "react";

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  useEffect(() => {
    let cancelled = false;
    fetch(url)
      .then((r) => r.json())
      .then((d) => {
        if (!cancelled) {
          setData(d);
          setLoading(false);
        }
      })
      .catch((e) => {
        if (!cancelled) {
          setError(e);
          setLoading(false);
        }
      });
    return () => { cancelled = true; };
  }, [url]);
  return [data, loading, error];
}

export default useFetch;

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 How many states does useFetch return?

  • Two
  • Four
  • Three Correct answer
  • One

Explanation: useFetch returns three states.

2 Loading flag

Question
useFetch starts loading as ____.
Answer
useFetch starts loading as true.

Explanation: loading starts as true.

3 Match the useFetch parts

Term Meaning
useState(null) data
useState(true) loading
fetch(url) Call
cancelled Cleanup

All lessons in Intermediate