Data Fetching in React

Fetching data from an external API is one of the most common tasks in a React application. This is typically handled within the useEffect hook to ensure the data is fetched when the component mounts.

1. Basic Fetching Pattern

To fetch data, you use the browser's native fetch() method inside a useEffect with an empty dependency array [].

JavaScript

import { useState, useEffect } from 'react';

function UserList() {
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/users')
      .then((response) => response.json())
      .then((data) => setUsers(data));
  }, []); // Empty array ensures this runs once on mount

  return (
    <ul>
      {users.map(user => (
        <li key={user.id}>{user.name}</li>
      ))}
    </ul>
  );
}          

2. Handling Loading and Error States

In real-world apps, it's important to show a loading spinner while waiting for data and an error message if the fetch fails.

JavaScript

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

  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch('https://api.example.com/data');
        if (!response.ok) throw new Error('Network response was not ok');
        const result = await response.json();
        setData(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, []);

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

  return <div>{JSON.stringify(data)}</div>;
}          

Note: Always include a cleanup function or use an AbortController if your component might unmount while a fetch is still in progress to avoid memory leaks.