Fetch API in React allows you to make HTTP requests to fetch data from a server. It is a built-in browser API that provides a way to interact with web services and APIs, replacing older methods like XMLHttpRequest.

Earlier, React developers often used libraries like Axios for HTTP requests instead of AJAX or the native Fetch API. However, Fetch API is now the standard due to its native support, simplicity, and promise-based structure. While Axios is still popular for its additional features like automatic JSON transformation and interceptors, Fetch API is preferred for lightweight applications.

Fetch is commonly used with the useEffect hook to fetch data when a component mounts, ensuring proper handling of side effects in React's lifecycle.


Fetch API

Here's an example of how to use the Fetch API in a React component to fetch data from an API. We are using the useEffect hook to fetch data when the component mounts.

Note: Fetch API should always be used within useEffect to manage side effects properly. Without useEffect, it can cause infinite re-renders or other lifecycle issues.


import { useEffect } from "react";

function fetchData(){

     useEffect(() => {
     fetch("https://api.example.com/data")
          .then((response) => response.json())
          .then((data) => {
               console.log(data);
          })
          .catch((error) => {
               console.error("Error fetching data:", error);
          });
     }, []);   // Empty array means this effect runs once on mount
     
     return <div>Check the console for fetched data.</div>;
}

export default FetchData;

Bind data from fetch API in React

To bind data from a fetch API in React, we typically use the useState and useEffect hooks. Using async/await improves readability and avoids callback hell. It's also good practice to handle loading states and errors for a better user experience.

Here's an example with loading and error handling:


import { useState, useEffect } from "react";

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

     async function fetchApi() {
          const url = "https://jsonplaceholder.typicode.com/users";

          try {
               setLoading(true);
               let res = await fetch(url);
               if (!res.ok) {
                    throw new Error(`error: ${res.status}`);
               }
               res = await res.json();
               setData(res);
               setError(null);
          } catch (err) {
               setError(err.message);
               console.warn(err);
          } finally {
               setLoading(false);
          }
     }

     useEffect(() => {
          fetchApi();
     }, []); 

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

     return (
          <div>
               <h2>Fetched Data</h2>
               <table>
                    <thead>
                         <tr>
                              <th>Id</th>
                              <th>Name</th>
                              <th>Phone</th>
                              <th>Email</th>
                         </tr>
                    </thead>
                    <tbody>
                         {data.map((item) => (
                              <tr key={item.id}>
                                   <td>{item.id}</td>
                                   <td>{item.name}</td>
                                   <td>{item.phone}</td>
                                   <td>{item.email}</td>
                              </tr>
                         ))}
                    </tbody>      
               </table>
                    
          </div>
     );
}

export default FetchData;

Sort Data

After fetching data, you can sort it using JavaScript's array methods like sort(). Here's an improved example with clickable headers for sorting and proper state management:

For example:


import { useState, useEffect } from "react";

function FetchDataWithSort(){
     const [data, setData] = useState([]);
     const [sortConfig, setSortConfig] = useState({ key: null, direction: 'asc' });

     async function fetchApi() {
          const url = "https://jsonplaceholder.typicode.com/users";

          try {
               let res = await fetch(url);
               res = await res.json();
               setData(res);
          } catch (err) {
               console.warn(err);
          }
     }

     useEffect(() => {
          fetchApi();
     }, []); 

     const handleSort = (key) => {
          let direction = 'asc';
          if (sortConfig.key === key && sortConfig.direction === 'asc') {
               direction = 'desc';
          }
          setSortConfig({ key, direction });

          const sortedData = [...data].sort((a, b) => {
               if (a[key] < b[key]) {
                    return direction === 'asc' ? -1 : 1;
               }
               if (a[key] > b[key]) {
                    return direction === 'asc' ? 1 : -1;
               }
               return 0;
          });
          setData(sortedData);
     };

     return (
          <div>
               <h2>Fetched Data</h2>
               <table>
                    <thead>
                         <tr>
                              <th onClick={() => handleSort('id')}>Id {sortConfig.key === 'id' ? (sortConfig.direction === 'asc' ? '↑' : '↓') : ''}</th>
                              <th onClick={() => handleSort('name')}>Name {sortConfig.key === 'name' ? (sortConfig.direction === 'asc' ? '↑' : '↓') : ''}</th>
                              <th onClick={() => handleSort('phone')}>Phone {sortConfig.key === 'phone' ? (sortConfig.direction === 'asc' ? '↑' : '↓') : ''}</th>
                              <th onClick={() => handleSort('email')}>Email {sortConfig.key === 'email' ? (sortConfig.direction === 'asc' ? '↑' : '↓') : ''}</th>
                         </tr>
                    </thead>
                    <tbody>
                         {data.map((item) => (
                              <tr key={item.id}>
                                   <td>{item.id}</td>
                                   <td>{item.name}</td>
                                   <td>{item.phone}</td>
                                   <td>{item.email}</td>
                              </tr>
                         ))}
                    </tbody>      
               </table>
                    
          </div>
     );
}

export default FetchDataWithSort;