Making API Calls with React Hooks: Handling Loading States

Introduction to React Hooks

React Hooks have revolutionized the way we manage state and side effects in functional components. Introduced in React 16.8, hooks allow developers to use state and other React features without writing a class component. One of the most common use cases for hooks is handling API calls, where we can leverage hooks like useState and useEffect to fetch data and manage loading states efficiently.

In this tutorial, we’ll explore how to make API calls in React using hooks, focusing specifically on handling loading states effectively. Understanding how to manage loading states can improve user experience significantly by providing visual feedback while data is being fetched.

We will build a simple React application to display a list of users fetched from a public API, demonstrating how to handle loading states, display error messages, and render the fetched data in a user-friendly way.

Setting Up the Project

To get started, we will set up a new React project using create-react-app. If you haven’t already, make sure you have Node.js installed on your computer. Open your terminal and run the following command:

npx create-react-app api-hooks-example

This command will create a new React application named api-hooks-example. Once the project is created, navigate to the project directory:

cd api-hooks-example

Next, you can start the development server to see the initial app:

npm start

Your app should now be running on http://localhost:3000. Now, let’s create a component that will handle our API call.

Creating the User Component

We will create a new component called UserList.js that will fetch a list of users from the JSONPlaceholder API. Inside the src directory of your project, create a new folder called components and a new file named UserList.js.

In UserList.js, we will import React, useState, and useEffect:

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

Next, define the UserList component and set up the initial state for loading, data, and error:

const UserList = () => { const [loading, setLoading] = useState(true); const [users, setUsers] = useState([]); const [error, setError] = useState(null); ... }

In the component, we will use the useEffect hook to fetch data from the API when the component mounts. Inside useEffect, we will implement the API call:

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); setLoading(false); }); }, []);

This code fetches user data from the API, manages the loading state, and handles potential errors. The empty dependency array ensures this effect runs only once when the component mounts.

Handling Loading States and Errors

Now that we have the data-fetching logic set up, we can handle different states of our component: loading, error, and data display. First, we’ll manage the loading state. If the data is still being fetched, we want to show a loading message:

if (loading) { return 
Loading...
; }

If there’s an error during the fetch, we’ll display an error message:

if (error) { return 
Error: {error.message}
; }

Finally, if the data is successfully fetched, we can render the list of users:

return ( 

User List

    {users.map(user => (
  • {user.name}
  • ))}
);

Putting it all together, your UserList.js component should look like this:

const UserList = () => { const [loading, setLoading] = useState(true); const [users, setUsers] = useState([]); 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); setLoading(false); }); }, []); if (loading) { return 
Loading...
; } if (error) { return
Error: {error.message}
; } return (

User List

    {users.map(user => (
  • {user.name}
  • ))}
); };

Integrating the User Component into Your App

Now that our UserList component is ready, we need to integrate it into our main application component. Open the src/App.js file, and import the UserList component:

import UserList from './components/UserList';

Next, we can use the UserList component within the App component’s render method:

function App() { return ( 

API Call with React Hooks

); }

Your complete App.js file should now look like this:

import React from 'react'; import './App.css'; import UserList from './components/UserList'; function App() { return ( 

API Call with React Hooks

); }

Now save all your changes and head back to your browser where your React app is running. You should see a loading message initially, followed by the list of users once the API call is completed.

Conclusion and Further Improvements

In this tutorial, we learned how to make API calls using React Hooks, focusing on managing loading states and errors. By using the useState and useEffect hooks, we were able to create a functional component that fetches data and provides visual feedback to users.

There are many ways you could further improve this implementation. For instance, you could add more user details, implement search functionality, or improve error handling by retrying failed requests. Additionally, as you advance, consider exploring libraries like axios for HTTP requests or React Query for simpler data fetching and caching.

This project’s simplicity demonstrates the basic principles of making API calls with React Hooks, giving you a solid foundation to build upon. As you dive deeper into React and JavaScript, continue to explore innovative ways to enhance user experience and application performance.

Scroll to Top