REACT Fetch API

The Fetch API is a built-in browser interface used to make HTTP requests to servers. In React, the Fetch API is commonly used to retrieve or send data from/to an API.

Basics of Fetch API

The fetch() function is used to make HTTP requests. It returns a Promise that resolves to the Response object.

Syntax

fetch(url, options)
  .then(response => response.json())
  .then(data => {
    // Handle data
  })
  .catch(error => {
    // Handle errors
  });

Try It Now

Using Fetch API in React

 

1. Fetching Data (GET Request)

Fetch data from a REST API when the component renders.

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

const App = () => {
  const [data, setData] = useState(null); // State for storing fetched data
  const [loading, setLoading] = useState(true); // Loading state
  const [error, setError] = useState(null); // Error state

  useEffect(() => {
    fetch('https://jsonplaceholder.typicode.com/posts')
      .then((response) => {
        if (!response.ok) {
          throw new Error('Failed to fetch data'); // Handle HTTP errors
        }
        return response.json(); // Parse JSON
      })
      .then((data) => {
        setData(data); // Store data
        setLoading(false); // Stop loading
      })
      .catch((error) => {
        setError(error.message); // Handle errors
        setLoading(false);
      });
  }, []); // Empty dependency array -> runs only on the first render

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

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

export default App;

Try It Now

2. Sending Data (POST Request)

Send data to a server using POST.

import React, { useState } from 'react';

const App = () => {
  const [title, setTitle] = useState('');
  const [body, setBody] = useState('');
  const [response, setResponse] = useState(null);

  const handleSubmit = (e) => {
    e.preventDefault();

    fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST', // Specify the HTTP method
      headers: {
        'Content-Type': 'application/json', // Set content type
      },
      body: JSON.stringify({
        title,
        body,
        userId: 1, // Example payload
      }),
    })
      .then((response) => response.json())
      .then((data) => setResponse(data))
      .catch((error) => console.error('Error:', error));
  };

  return (
    <div>
      <h1>Create Post</h1>
      <form onSubmit={handleSubmit}>
        <input
          type="text"
          placeholder="Title"
          value={title}
          onChange={(e) => setTitle(e.target.value)}
        />
        <textarea
          placeholder="Body"
          value={body}
          onChange={(e) => setBody(e.target.value)}
        ></textarea>
        <button type="submit">Submit</button>
      </form>
      {response && (
        <div>
          <h2>Response</h2>
          <p>Post created with ID: {response.id}</p>
        </div>
      )}
    </div>
  );
};

export default App;

Try It Now

3. Using Async/Await Syntax

Instead of .then chaining, you can use async/await for better readability.

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

const App = () => {
  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://jsonplaceholder.typicode.com/posts');
        if (!response.ok) {
          throw new Error('Failed to fetch data');
        }
        const data = await response.json();
        setData(data);
        setLoading(false);
      } catch (error) {
        setError(error.message);
        setLoading(false);
      }
    };

    fetchData();
  }, []);

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

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

export default App;

Try It Now

Error Handling

Always check if the response is okay (response.ok) to handle HTTP errors gracefully. Use .catch to handle network errors.

 

Common HTTP Methods

  1. GET: Retrieve data (e.g., fetch posts or users).
  2. POST: Create new data on the server (e.g., add a new user or post).
  3. PUT: Replace an existing resource.
  4. PATCH: Update parts of a resource.
  5. DELETE: Remove a resource.

Best Practices

  1. Use try-catch with Async/Await: Makes error handling cleaner.
  2. Handle Loading State: Show loading spinners or messages while data is being fetched.
  3. Use Headers Properly: Set headers for APIs that require authentication (e.g., adding a token).
  4. Debounce Requests: When fetching on user input (like search), debounce the API calls to reduce unnecessary requests.
  5. Use a Custom Hook: Extract fetch logic into a reusable custom hook.

Advanced Topics

  • Custom Hooks for Fetch: Reuse fetch logic.
  • Error Boundaries: Catch errors in React components.
  • Libraries like Axios: For better API handling with additional features (e.g., request cancellation).