Fetch and Display Data from an API in React

Recently, while working on a React dashboard for a U.S.-based client, I needed to fetch real-time data from a public API and display it neatly in a table.

At first, I thought it would be an easy task, just call the API and show the results. But as I started implementing it, I realized there were a few key points that could make or break the user experience, especially when dealing with asynchronous data and loading states.

In this tutorial, I’ll show you two simple and practical ways to fetch and display data from an API in a React functional component. We’ll start with the built-in fetch() method and then move on to using Axios, a popular HTTP client that makes handling responses easier.

Method 1 – Use the Fetch API in React

The simplest way to fetch data in React is by using the built-in fetch() method. It works well for most use cases and doesn’t require installing any extra libraries.

Here’s how I usually do it.

Step 1 – Set Up the Project

Open your terminal and create a new React app using:

npx create-react-app fetch-api-demo
cd fetch-api-demo
npm start

This will create a new React project and start the development server.

Step 2 – Write the Code

Now, open the src/App.js file and replace its content with the following code:

import React, { useEffect, useState } from "react";

function App() {
  const [users, setUsers] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch("https://jsonplaceholder.typicode.com/users")
      .then((response) => {
        if (!response.ok) {
          throw new Error("Network response was not ok");
        }
        return response.json();
      })
      .then((data) => {
        setUsers(data);
        setLoading(false);
      })
      .catch((error) => {
        setError(error.message);
        setLoading(false);
      });
  }, []);

  if (loading) {
    return <p>Loading users...</p>;
  }

  if (error) {
    return <p style={{ color: "red" }}>Error: {error}</p>;
  }

  return (
    <div style={{ width: "80%", margin: "40px auto", fontFamily: "Arial" }}>
      <h2>Fetched Users from API</h2>
      <table
        border="1"
        cellPadding="10"
        style={{ borderCollapse: "collapse", width: "100%" }}
      >
        <thead>
          <tr style={{ backgroundColor: "#f2f2f2" }}>
            <th>ID</th>
            <th>Name</th>
            <th>Email</th>
            <th>City</th>
          </tr>
        </thead>
        <tbody>
          {users.map((user) => (
            <tr key={user.id}>
              <td>{user.id}</td>
              <td>{user.name}</td>
              <td>{user.email}</td>
              <td>{user.address.city}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

export default App;

You can refer to the screenshot below to see the output.

Fetch and Display Data from an API in React

Step 3 – Understand the Code

Here’s what’s happening in the code above:

  • I used the useEffect hook to fetch data when the component first loads.
  • The fetch() function sends a GET request to the JSONPlaceholder API (a free public API often used for testing).
  • Once the data is received, it’s stored in the user’s state variable.
  • If there’s an error, it’s caught and displayed on the screen.
  • A simple table layout is used to display the fetched data.

This is a clean and minimal approach that works great for small to medium-sized applications.

Method 2 – Use Axios in React

While the fetch() API works fine, I often prefer Axios because it simplifies error handling and supports features like request cancellation and interceptors.

Step 1 – Install Axios

Run the following command in your project directory:

npm install axios

Step 2 – Fetch Data Using Axios

Replace your App.js content with the code below:

import React, { useEffect, useState } from "react";
import axios from "axios";

function App() {
  const [posts, setPosts] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState("");

  useEffect(() => {
    axios
      .get("https://jsonplaceholder.typicode.com/posts")
      .then((response) => {
        setPosts(response.data);
        setLoading(false);
      })
      .catch((err) => {
        setError(err.message);
        setLoading(false);
      });
  }, []);

  if (loading) {
    return <p>Loading posts...</p>;
  }

  if (error) {
    return <p style={{ color: "red" }}>Error: {error}</p>;
  }

  return (
    <div style={{ width: "80%", margin: "40px auto", fontFamily: "Arial" }}>
      <h2>Fetched Posts from API</h2>
      <ul style={{ listStyleType: "none", padding: 0 }}>
        {posts.slice(0, 10).map((post) => (
          <li
            key={post.id}
            style={{
              backgroundColor: "#f9f9f9",
              marginBottom: "10px",
              padding: "15px",
              borderRadius: "5px",
              boxShadow: "0 1px 3px rgba(0,0,0,0.1)",
            }}
          >
            <h3>{post.title}</h3>
            <p>{post.body}</p>
          </li>
        ))}
      </ul>
    </div>
  );
}

export default App;

You can refer to the screenshot below to see the output.

Fetch and Display Data from an API React

Step 3 – Why I Prefer Axios

  • Axios automatically parses JSON responses, so you don’t need to call .json().
  • It provides better error messages and response handling.
  • You can set up global defaults (like base URLs or headers) easily.

For example, if you’re working with a U.S.-based API such as the U.S. Census Bureau API or OpenWeatherMap, Axios makes it easier to include API keys and custom headers.

Bonus Tip – Display a Loading Spinner

When fetching data from APIs, it’s always a good idea to show a loading spinner instead of plain text. You can use a simple CSS spinner or a library like React Loading. Here’s a quick example using pure CSS:

function Spinner() {
  return (
    <div style={{ textAlign: "center", marginTop: "50px" }}>
      <div
        style={{
          border: "6px solid #f3f3f3",
          borderTop: "6px solid #3498db",
          borderRadius: "50%",
          width: "40px",
          height: "40px",
          animation: "spin 1s linear infinite",
          margin: "auto",
        }}
      ></div>
      <p>Loading data...</p>
      <style>
        {`
          @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
          }
        `}
      </style>
    </div>
  );
}

You can then replace your loading text with <Spinner /> in either of the above methods.

Common Mistakes to Avoid

  • Not handling errors properly: Always include .catch() or a try/catch block.
  • Forgetting cleanup: If you’re fetching data repeatedly (like in live dashboards), cancel requests when the component unmounts.
  • Updating state after unmount: This can cause memory leaks. Use a cleanup function inside useEffect.

Fetching and displaying data from an API in React is one of those essential skills every developer needs.

In this tutorial, I showed you two effective ways to do it, using the built-in fetch() API and the more powerful Axios library. Both methods work great depending on your project’s needs.

If you’re working on a small project or learning the basics, start with fetch(). For larger applications or APIs that require authentication and complex headers, go with Axios.

You may also like to read:

Leave a Comment

51 Python Programs

51 PYTHON PROGRAMS PDF FREE

Download a FREE PDF (112 Pages) Containing 51 Useful Python Programs.

pyython developer roadmap

Aspiring to be a Python developer?

Download a FREE PDF on how to become a Python developer.

Let’s be friends

Be the first to know about sales and special discounts.