DEV Community

Cover image for How To Fetch Data from an API and Display It in React.js
Udemezue John
Udemezue John

Posted on

How To Fetch Data from an API and Display It in React.js

Introduction.

Fetching data from an API and displaying it in a React app is an essential skill for any web developer.

React, with its component-based architecture, makes it relatively straightforward to handle API requests and manage state, but getting everything set up correctly still requires some care and attention.

In this post, I’ll walk through how to properly fetch data from an API and display it within a React component.

How Do I Fetch Data from an API and Display It in React.js?

Fetching data from an API is a common task in modern web development. React.js makes this process relatively straightforward, but if you're new to it, navigating asynchronous data fetching, state management, and rendering can feel a bit intimidating.

In this article, I'll walk through how to fetch data from an API in React and display it effectively, making use of React’s built-in hooks like useState and useEffect.

Setting Up the Project.

First, if you don’t already have a React app set up, you'll want to create one.

You can easily spin up a new React app using the create-react-app command. If you have Node.js installed, run the following command:

npx create-react-app api-fetching
cd api-fetching
npm start

Enter fullscreen mode Exit fullscreen mode

This will set up a new React app for you. Open it up in your favorite code editor, and let’s get started!

The Basic Steps to Fetch Data.

Fetching data from an API and displaying it in React follows a basic process:

  • Identify the API: Find the API URL from where you need to fetch the data.
  • Make the API Call: Use fetch() or a library like axios to make the call.
  • Manage State: Use React’s useState hook to store the data.
  • Trigger the API Call: Use useEffect to make the API call when the component mounts.
  • Render the Data: Display the data in your JSX.

Let’s dive into each step in more detail.

Step 1: Identify the API.

For this example, I'll fetch some data from a public API. One great resource is the JSONPlaceholder API, which offers a range of dummy data.

I'll be fetching a list of posts from this API, which is accessible via the following URL:

https://jsonplaceholder.typicode.com/posts
Enter fullscreen mode Exit fullscreen mode

Step 2: Make the API Call with fetch().

The fetch() method is a built-in browser API for making HTTP requests. Here’s how you can use it in React:

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

function App() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then((response) => response.json())
      .then((data) => setPosts(data))
      .catch((error) => console.error('Error fetching data:', error));
  }, []);

  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

Let’s break this down:

  • State Management: I use useState to create a state variable posts and a function setPosts to update it. This state will hold the data returned from the API.
  • Effect Hook: useEffect is a hook that allows me to run side effects like data fetching in a function component. In this case, I want the data fetching to happen when the component first mounts, so I provide an empty dependency array ([]) to run the effect once.
  • fetch() Function: I call fetch() with the API URL, which returns a promise. Once the promise resolves, I convert the response to JSON using .json(). Then, I update the posts state with the fetched data using setPosts.

Step 3: Handling Errors.

It's essential to handle errors gracefully, especially when dealing with external APIs.

In the above code, I use .catch() to log any errors that occur during the fetch operation.

However, you can take it a step further by displaying an error message to users if something goes wrong:

function App() {
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState(null);

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

  return (
    <div>
      <h1>Posts</h1>
      {error ? <p>{error}</p> : null}
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Step 4: Displaying the Data.

In the return statement, I iterate over the posts array using the .map() method to render each post in an unordered list

    .

    Optional: Using axios for API Calls

    While fetch() works well, some developers prefer using axios because it simplifies syntax and provides better error handling. Here’s how you can achieve the same thing using axios:

    First, install axios:

npm install axios

Then, modify the API call:

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

function App() {
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState(null);

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

  return (
    <div>
      <h1>Posts</h1>
      {error ? <p>{error}</p> : null}
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

export default App;

With axios, the code becomes slightly more concise and the error handling is built into the library.

Step 5: Loading States and Conditional Rendering.

Fetching data from an API is inherently asynchronous, which means there’s a delay between when the request is made and when the data is available.

During this delay, it's a good practice to show a loading indicator to the user. You can easily implement this by adding a loading state:

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

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

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

  if (error) {
    return <p>{error}</p>;
  }

  return (
    <div>
      <h1>Posts</h1>
      <ul>
        {posts.map((post) => (
          <li key={post.id}>{post.title}</li>
        ))}
      </ul>
    </div>
  );
}

In this code:

I added a loading state that is initially set to true.

The loading state is set to false once the data is successfully fetched or if an error occurs.

While loading is true, a "Loading..." message is displayed. Once the data is fetched, the posts are displayed. If an error occurs, the error message is displayed.

Conclusion.

Fetching data from an API in React is a foundational skill for any React developer. Whether you use the built-in fetch() method or a third-party library like axios, the process is quite manageable.

Using React’s useState and useEffect hooks makes it easy to handle state and side effects, and with proper error handling and loading states, you can ensure a smooth user experience.

React’s declarative nature makes it simple to render dynamic content once the data is available.

From here, you can expand upon this by incorporating more complex APIs, authentication, or handling pagination, among other tasks.

Top comments (0)