How to Make a Call to an API in React


For most React applications, making an HTTP request happens through either the axios library or the Fetch API. Since the introduction of hooks in React 16.8, we’ve seen the rise of custom useFetch hooks for API calls.

Custom useFetch() Hook

This is the one I personally use, since it will return the data, any errors, and the isLoading state.

I would recommend creating a separate useFetch.js for this hook (maybe even a /utils folder to hold all your custom hooks).

// ./src/utils/useFetch.js
import { useState, useEffect } from "react";

export const useFetch = (url, options) => {
  const [data, setData] = useState(null);
  const [error, setError] = useState(null);
  const [isLoading, setIsLoading] = useState(false);

  useEffect(() => {
    const runFetch = async () => {
      setIsLoading(true);
      try {
        const res = await fetch(url, options);
        const json = await res.json();
        setData(json);
        setIsLoading(false);
      } catch (error) {
        setError(error);
      }
    };
    runFetch();
  }, []);
  return { data, error, isLoading };
};

The input to useFetch() are the following:

  1. url: the API URL
  2. options: Fetch API options

In our example, we’re going to make a call to the fake API https://jsonplaceholder.typicode.com/todos/1, which returns this:

{
  "userId": 1,
  "id": 1,
  "title": "delectus aut autem",
  "completed": false
}

Example with useFetch()

// ./src/App.js
import React from "react";
import { useFetch } from "./utils/useFetch";

const App = () => {
  // Example API
  const url = "https://jsonplaceholder.typicode.com/todos/1";
  // Use all native fetch options
  const options = {};
  // Use our custom hook
  const { data, error, isLoading } = useFetch(url, options);
  return (
    <div>
      {!data && isLoading && "Loading..."}
      {!data && error && "Error..."}
      {data && data.map((x) => <div key={x.id}>{x.title}</div>)}
    </div>
  );
};