DEV Community

Cover image for How To Fetch API In React JS
Udemezue John
Udemezue John

Posted on

How To Fetch API In React JS

Introduction.

Fetching data from an API is one of the most essential skills when working with React JS, especially as modern web applications increasingly rely on external data sources.

In React, API requests can be easily handled using built-in JavaScript features such as the fetch function, third-party libraries like Axios, or more advanced techniques like React hooks and context for state management.

Each method comes with its own advantages and nuances, and knowing which one to use can make a big difference in your application’s performance and maintainability.

This guide covers everything needed to fetch data effectively in React.

Understanding API Calls in React

In modern web development, APIs (Application Programming Interfaces) serve as a bridge between your frontend React app and backend services.

These services might provide data in various formats, like JSON, XML, or others.

In most cases, the data is retrieved over HTTP, and it's crucial to handle this process efficiently in React.

React handles API calls using JavaScript's built-in fetch function or with libraries like Axios, which simplifies the process. I'll cover both approaches and show you where each one shines.

How Do I Fetch API In React JS?

Fetching data from an API is one of the most common tasks in React development, especially when building dynamic, data-driven applications.

Let’s break down how to fetch data from APIs in React, using both the fetch API and Axios, two of the most popular methods.

Step 1: Setting Up a Basic React App.

Before fetching data, I need to ensure the environment is set up properly. I’ll start with a basic React app:

npx create-react-app fetch-api-demo
cd fetch-api-demo
npm start
Enter fullscreen mode Exit fullscreen mode

This command scaffolds a simple React application. Once the app is running, I can see the default "Create React App" page.

Step 2: Using Fetch to Make API Calls.

The simplest way to fetch data in React is by using the native fetch method.

It’s built into JavaScript, requires no additional libraries, and works well for most use cases.

Here's how I can use it in a React component:

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

function App() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

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

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

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

export default App;
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • useEffect Hook: This hook runs when the component mounts. It ensures that the data fetch happens only once when the component loads. I pass an empty dependency array ([]) to make sure the effect doesn't run on every render, only on the initial one.
  • fetch Method: I make the actual API call using fetch. In this case, I'm fetching data from the JSONPlaceholder API, a free-to-use service that returns dummy data. The .then method chains the promises, parsing the response as JSON.
  • State Management: I use the useState hook to store both the data and the loading state. While the data is being fetched, loading remains true and displays a loading message. Once the data is retrieved, loading is set to false, and the data is displayed.

Error Handling.

Handling errors is critical for a good user experience. With fetch, the catch block helps me handle any issues during the fetch process, such as network errors.

Step 3: Using Axios to Make API Calls.

While fetch is straightforward, some developers prefer using Axios due to its simplicity and additional features.

Axios has built-in support for older browsers, handles JSON automatically, and allows for easier request cancellation and timeouts.

To use Axios, I first need to install it:

npm install axios
Enter fullscreen mode Exit fullscreen mode

Now, I'll modify the code to use Axios instead of fetch:

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

function App() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    axios
      .get('https://jsonplaceholder.typicode.com/posts')
      .then((response) => {
        setData(response.data);
        setLoading(false);
      })
      .catch((error) => console.error('Error fetching data:', error));
  }, []);

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

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

export default App;
Enter fullscreen mode Exit fullscreen mode

Differences between Axios and fetch:

  • Automatic JSON Parsing: Axios automatically parses the response, whereas with fetch, I need to manually convert the response to JSON using response.json().
  • Additional Features: Axios provides built-in functionality for interceptors, request and response transformations, and automatic handling of timeouts, which are not as straightforward with fetch.
  • Error Handling: Axios has simpler and more powerful error handling. It automatically throws an error for HTTP status codes that fall outside of the 2xx range, whereas fetch only rejects the promise for network errors (not for other HTTP errors like 404 or 500).

Step 4: Loading and Error States.

It's crucial to properly manage loading and error states for a seamless user experience.

Here’s a more refined version of the code that handles loading, data, and potential errors gracefully:

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

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

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

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

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

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

export default App;
Enter fullscreen mode Exit fullscreen mode

In this version, I added an error state using the useState hook. This ensures that if the API call fails, an appropriate error message is displayed instead of breaking the app.

Step 5: Fetching Data Conditionally.

Sometimes, I might not want to fetch data immediately when the component mounts but instead based on a user interaction.

For instance, I can trigger a data fetch on a button click:

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

function App() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(false);

  const fetchData = () => {
    setLoading(true);
    axios
      .get('https://jsonplaceholder.typicode.com/posts')
      .then((response) => {
        setData(response.data);
        setLoading(false);
      })
      .catch((error) => {
        console.error('Error fetching data:', error);
        setLoading(false);
      });
  };

  return (
    <div>
      <button onClick={fetchData}>Fetch Data</button>
      {loading && <p>Loading...</p>}
      {data && (
        <ul>
          {data.map((post) => (
            <li key={post.id}>{post.title}</li>
          ))}
        </ul>
      )}
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, the data is only fetched when the "Fetch Data" button is clicked. The loading indicator shows while the API request is in progress.

Conclusion.

Fetching data in React can seem daunting at first, but once I break it down, it's straightforward.

Both the fetch API and Axios offer powerful tools to work with, and the choice between them often comes down to personal preference and project requirements.

For simpler needs, fetch works perfectly. However, if I need more control over my HTTP requests, Axios is a solid option that adds convenience with additional features.

No matter which tool I choose, managing loading and error states ensures a smooth user experience, keeping users informed of what's happening as data loads or if something goes wrong.

Top comments (0)