API Calls in React with Axios and Fetch


When building modern web applications, making API calls is a common requirement. React offers two popular ways to handle HTTP requests: Axios and Fetch API. Both methods allow you to interact with RESTful APIs to perform CRUD operations like GET, POST, PUT, and DELETE.

API Calls in React with Axios and Fetch

In this guide, we will cover:

  1. Setting up Axios and Fetch
  2. Making GET, POST, PUT, DELETE requests
  3. Best practices for handling API calls
  4. Frequently Asked Questions (FAQs)

This tutorial is designed for both beginners and experienced developers to effectively make API calls in React using these two powerful tools.

Why Use Axios and Fetch for API Calls?

  • Axios is a promise-based HTTP client for the browser and Node.js. It simplifies HTTP requests and provides additional features like interceptors, request cancellation, and timeout handling.
  • Fetch API is a built-in JavaScript function for making network requests. It is lightweight and modern but may require more manual handling of errors compared to Axios.

Setting Up Axios

Install Axios in your React project using npm:

npm install axios

Import Axios in your component:

import axios from 'axios';

For Fetch API, no installation is required as it is built into JavaScript.

1. GET Request in React

Using Fetch API

File: App.js

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

const App = () => {
  const [data, setData] = useState([]);

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

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

export default App;

Using Axios

File: App.js

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

const App = () => {
  const [data, setData] = useState([]);

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

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

export default App;

Explanation:

  • We use the useEffect hook to make the API call when the component mounts.
  • The useState hook is used to store the fetched data.
  • Error handling is done using .catch().

2. POST Request in React

Using Fetch API

File: CreatePost.js

import React, { useState } from 'react';

const CreatePost = () => {
  const [title, setTitle] = useState('');
  const [body, setBody] = useState('');

  const handleSubmit = () => {
    fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        title,
        body,
      }),
    })
      .then((response) => response.json())
      .then((data) => console.log('Success:', data))
      .catch((error) => console.error('Error:', error));
  };

  return (
    <div>
      <h2>Create Post</h2>
      <input
        type="text"
        placeholder="Title"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <textarea
        placeholder="Body"
        value={body}
        onChange={(e) => setBody(e.target.value)}
      />
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
};

export default CreatePost;

Using Axios

File: CreatePost.js

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

const CreatePost = () => {
  const [title, setTitle] = useState('');
  const [body, setBody] = useState('');

  const handleSubmit = () => {
    axios
      .post('https://jsonplaceholder.typicode.com/posts', {
        title,
        body,
      })
      .then((response) => console.log('Success:', response.data))
      .catch((error) => console.error('Error:', error));
  };

  return (
    <div>
      <h2>Create Post</h2>
      <input
        type="text"
        placeholder="Title"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <textarea
        placeholder="Body"
        value={body}
        onChange={(e) => setBody(e.target.value)}
      />
      <button onClick={handleSubmit}>Submit</button>
    </div>
  );
};

export default CreatePost;

3. PUT Request in React

Using Axios

File: UpdatePost.js

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

const UpdatePost = () => {
  const [title, setTitle] = useState('');
  const [postId, setPostId] = useState('');

  const handleUpdate = () => {
    axios
      .put(`https://jsonplaceholder.typicode.com/posts/${postId}`, {
        title,
      })
      .then((response) => console.log('Updated:', response.data))
      .catch((error) => console.error('Error:', error));
  };

  return (
    <div>
      <h2>Update Post</h2>
      <input
        type="text"
        placeholder="Post ID"
        value={postId}
        onChange={(e) => setPostId(e.target.value)}
      />
      <input
        type="text"
        placeholder="New Title"
        value={title}
        onChange={(e) => setTitle(e.target.value)}
      />
      <button onClick={handleUpdate}>Update</button>
    </div>
  );
};

export default UpdatePost;

4. DELETE Request in React

Using Fetch API

File: DeletePost.js

import React, { useState } from 'react';

const DeletePost = () => {
  const [postId, setPostId] = useState('');

  const handleDelete = () => {
    fetch(`https://jsonplaceholder.typicode.com/posts/${postId}`, {
      method: 'DELETE',
    })
      .then(() => console.log(`Post ${postId} deleted`))
      .catch((error) => console.error('Error:', error));
  };

  return (
    <div>
      <h2>Delete Post</h2>
      <input
        type="text"
        placeholder="Post ID"
        value={postId}
        onChange={(e) => setPostId(e.target.value)}
      />
      <button onClick={handleDelete}>Delete</button>
    </div>
  );
};

export default DeletePost;

Axios vs Fetch : Which One Should You Use?

Both Axios and Fetch are popular choices for making HTTP requests in React, but they have some key differences. Understanding these differences can help you decide which one is best for your project.

1. Syntax and Ease of Use

  • Axios: Axios has a simpler and more intuitive syntax. It automatically parses JSON responses, making it easier to work with API data. Example:
  axios.get('https://jsonplaceholder.typicode.com/posts')
    .then(response => console.log(response.data))
    .catch(error => console.error(error));
  • Fetch: Fetch is a more raw API, and it requires additional steps for handling response data, especially for parsing JSON. Example:
  fetch('https://jsonplaceholder.typicode.com/posts')
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error(error));

2. Browser Support

  • Axios: Axios supports older browsers like Internet Explorer and also has built-in support for handling HTTP requests in Node.js, making it a good choice for server-side applications.
  • Fetch: Fetch is a newer API and may not be fully supported in older browsers like Internet Explorer. However, it’s widely supported in modern browsers.

3. Request and Response Interception

  • Axios: Axios provides powerful features like interceptors, which allow you to modify requests or responses before they are sent or received. This is useful for adding headers, handling authentication tokens, or logging. Example:
  axios.interceptors.request.use(
    config => {
      // Modify request
      config.headers.Authorization = 'Bearer token';
      return config;
    },
    error => {
      return Promise.reject(error);
    }
  );
  • Fetch: Fetch does not have built-in support for request or response interceptors. You would need to handle it manually, which can be more complex.

4. Handling Errors

  • Axios: Axios automatically throws an error if the HTTP status code is outside the 2xx range, making it easier to handle errors. Example:
  axios.get('https://jsonplaceholder.typicode.com/posts')
    .catch(error => {
      if (error.response) {
        console.log('Error:', error.response.status);
      } else {
        console.log('Network Error');
      }
    });
  • Fetch: Fetch only rejects the promise for network errors, so you have to manually check the response.ok property to handle non-2xx HTTP responses. Example:
  fetch('https://jsonplaceholder.typicode.com/posts')
    .then(response => {
      if (!response.ok) {
        throw new Error('Network response was not ok');
      }
      return response.json();
    })
    .catch(error => console.error('Error:', error));

5. Request Cancellation

  • Axios: Axios supports request cancellation using the CancelToken feature, which is useful if you need to cancel a request before it completes (e.g., in case of user navigation or page reloads). Example:
  const source = axios.CancelToken.source();

  axios.get('https://jsonplaceholder.typicode.com/posts', {
    cancelToken: source.token
  })
  .then(response => console.log(response.data))
  .catch(error => console.log(error));

  // To cancel the request
  source.cancel('Request canceled');
  • Fetch: Fetch does not support request cancellation natively, but you can use the AbortController API to achieve similar functionality. Example:
  const controller = new AbortController();
  const signal = controller.signal;

  fetch('https://jsonplaceholder.typicode.com/posts', { signal })
    .then(response => response.json())
    .then(data => console.log(data))
    .catch(error => console.error('Request canceled:', error));

  // To cancel the request
  controller.abort();

6. Performance

  • Axios: Axios is a bit heavier because of its additional features like interceptors, request/response transformations, and automatic JSON parsing. However, this overhead is usually minimal.
  • Fetch: Fetch is lightweight and built into the browser, so it doesn’t require any extra dependencies. This makes it a good choice for smaller projects where you want to avoid external libraries.

When to Use Axios:

  • If you need to support older browsers.
  • If you need advanced features like interceptors, request cancellation, or automatic JSON parsing.
  • If you prefer a simpler syntax and error handling.

When to Use Fetch:

  • If you want a lightweight solution with minimal dependencies.
  • If you’re working on a modern web app where browser support for Fetch is not an issue.
  • If you prefer using native browser APIs without relying on third-party libraries.

Best Practices

  1. Use Async/Await: For better readability and error handling.
  2. Error Handling: Implement robust error handling using try-catch blocks.
  3. Loading State: Show loading indicators during API calls.
  4. Environment Variables: Store API URLs in environment variables for flexibility.

FAQs

Q1. What is the difference between Axios and Fetch?

Axios provides more features like interceptors and automatic JSON parsing, while Fetch is a native API that requires manual handling of responses and errors.

Q2. Can I use both Axios and Fetch in one project?

Yes, but it’s better to choose one for consistency.

Q3. How do I handle errors in API calls?

Use .catch() for promises or try-catch blocks with async/await.

Q4. How do I make authenticated API calls in React?

Pass the authorization token in the request headers using Axios or Fetch.

Thank you for reading! If you found this guide helpful and want to stay updated on more React.js content, be sure to follow us for the latest tutorials and insights: JavaDZone React.js Tutorials. Happy coding!


Leave a Comment