April 22, 2024

HTTP DELETE Method in React - fetch, Axios

In this post we'll see how to use HTTP DELETE method in React applications in order to delete resources from a server. We'll see how to use fetch method in Fetch API and Axios to make DELETE requests with the help of examples.

fetch()- This method is used to call APIs across the network. GET is the default for fetch method.

With fetch() method you pass the URI and the body in case of PUT and POST and it returns a promise that resolves with a Response object.

Fetch syntax for DELETE method

fetch('url', {
  method: 'DELETE',
}) 
.then(response => response.json())
.then(data => console.log(data))
.catch((error) => console.log(error.message));

Axios- It is a promise-based HTTP Client for node.js and the browser. To make a DELETE request using Axios, you can use the axios.delete() method.

axios.delete(url[, config])

For API calls JSONPlaceholder is used which is a free fake API for testing and prototyping.

DELETE request in React with fetch returning Promise

For the delete example we'll use the GET example showed in this post- HTTP GET Method in React - fetch, Axios as base example which gets the 10 posts.

When displaying these posts delete button is also added with each post item now. On clicking the delete button respective post should get deleted.

HTTP DELETE Method in React

In the example there are two Components- Posts and PostItem.

Posts component does the job of fetching posts (limited to 10 posts) and that is done in the useEffect() hook.

PostItem component is used to display the fetched posts, so PostItem component acts as a presentational component.

posts.js

import axios from "axios";
import { useEffect, useState } from "react";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  useEffect(()=>{
    axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10')
    .then((response) => setPosts(response.data))
    .catch((error) => console.log("Error", error.message))
  }, []);

  const deletePost = (postId)=> {
    console.log('In delete post', postId);
    const url = 'https://jsonplaceholder.typicode.com/posts/' + postId;
    console.log(url);
    fetch(url, { method: 'DELETE' })
    .then(response => {
      console.log(response);
      if (!response.ok) {
        throw new Error('Error while deleting post data');
      }
    })
    .then(() => {
      console.log('Deleted Post Successfully...');
      // Filter out the deleted post so that it is not displayed
      const updatedPosts = posts.filter(post => post.id !== postId);  
      setPosts(updatedPosts);
    })
    .catch((error) => console.log("Error", error.message));
  }
    
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
          <PostItem key={post.id} post={post} onDeleteHandler={deletePost}></PostItem>
      )}
    </div>
  )
}

export default Posts;

In the code-

  1. useState() hook is used to maintain Posts state variable.
  2. fetch() method to get posts is called with in the useEffect() hook.
  3. deletePost() function has the logic to delete the post. In the URL, postId of the post that has to be deleted is added.
  4. Fetch method is called with method as ‘DELETE’ to delete the resource.
  5. From the fetch method a Promise is returned. In the then chaining you first check if the response is ok or not. If it is not an error is thrown that will be handled by catch. If response if ok then you filter out the post that has been deleted.
  6. Note that Bootstrap 5 is used for styling here. Refer Installing Bootstrap in React to know how to install Bootstrap in your React application.
  7. For displaying posts, post data is sent to the PostItem component that shows the parent to child component communication in React.
  8. For deleting post, even is sent from PostItem component that shows the child component to parent component communication in React.

postitem.js

const PostItem = (props) => {
  const onDeleteHandler = () => {
    props.onDeleteHandler(props.post.id);       
  }
  return (
    <>
      <h3>{props.post.title}</h3> 
      <div>
        <span>{props.post.body}</span>
        <div className="text-end">
          <button className="btn btn-danger" onClick={onDeleteHandler}>Delete</button>
        </div>
      </div>
    </>
  );
}

export default PostItem;

As you can see React props are used to get data from parent component and to communicate with the parent too.

DELETE request using async/await with fetch

You can also use async/await to wait for completion of DELETE request rather than using Promise with .then chaining. Use of async/await makes the code more readable. You can use try/catch to handle errors with async/await.

Posts.js

import axios from "axios";
import { useEffect, useState } from "react";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  //const [error, setError] = useState();
  useEffect(()=>{
    axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10')
    .then((response) => setPosts(response.data))
    .catch((error) => console.log("Error", error.message))
  }, []);

  const deletePost = async (postId)=> {
    console.log('In delete post', postId);
    try{
      const url = 'https://jsonplaceholder.typicode.com/posts/' + postId;
      const response = await fetch(url, { method: 'DELETE' });
      if (!response.ok) {
        throw new Error('Error while deleting post data');
      }
      //const resData = await response.json(); 
      console.log('Deleted Post Successfully');
      const updatedPosts = posts.filter(post => post.id !== postId);  
      setPosts(updatedPosts);
    }catch(error){
      console.log(error.message);
    }
  }
    
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
        <PostItem key={post.id} post={post} onDeleteHandler={deletePost}></PostItem>
      )}
    </div>
  )
}

export default Posts;

There is no change in the other component PostItem so it can be used as shown in the above example.

Few points to note in the code-

  1. deletePost() method is async.
  2. You need to wait for the response so await is used with the fetch method.
  3. Check for the response status and throw an error if response status is not ok.
  4. Code is enclosed in try/catch block to handle the thrown error.

DELETE request using async/await with error message

In the above React fetch method example with async/await, error message is logged to the console. If you want to display the error to the user then you can create one more component for Error. In the Posts component have the state for Error and set the Error in case one is thrown.

ErrorMessage.js

Uses the Bootstrap alert to show the error message.

const ErrorMessage = (props) => {
  return(
    <>
      <div className="alert alert-warning alert-dismissible fade show" role="alert">
        <p>{props.message}</p>
              
        <button type="button" className="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
      </div>
    </>
  )
}
export default ErrorMessage;

posts.js

import axios from "axios";
import { useEffect, useState } from "react";
import ErrorMessage from "./ErrorMessage";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState();
  useEffect(()=>{
    axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10')
    .then((response) => setPosts(response.data))
    .catch((error) => setError(error))
  }, []);

  const deletePost = async (postId)=> {
    console.log('In delete post', postId);
    try{
      const url = 'https://jsonplaceholder.typicode.com/posts/' + postId;
      const response = await fetch(url, { method: 'DELETE' });
      if (!response.ok) {
        throw new Error('Error while deleting post data');
      }
      console.log('Deleted Post Successfully');
      const updatedPosts = posts.filter(post => post.id !== postId);  
      setPosts(updatedPosts);
    }catch(error){
      setError(error);
    }
  }

  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
    
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
        <PostItem key={post.id} post={post} onDeleteHandler={deletePost}></PostItem>
      )}
    </div>
  )
}

export default Posts;

Now in case something goes wrong while deleting a post you'll get an error message.

delete async await

Using HTTP DELETE method in React with Axios

If you want to use Axios library to make HTTP calls then the first thing is to install the Axios library.

Using npm

$ npm install axios

Using yarn

$ yarn add axios

DELETE request using Axios returning Promise - React Example

We'll use the same example as used with fetch method where we have two Components named Posts and PostItem.

import axios from "axios";
import { useEffect, useState } from "react";
import ErrorMessage from "./ErrorMessage";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState();
  useEffect(()=>{
    axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10')
    .then((response) => setPosts(response.data))
    .catch((error) => setError(error))
  }, []);

  const deletePost = (postId)=> {
    console.log('In delete post', postId);
    const url = 'https://jsonplaceholder.typicode.com/posts/' + postId;
    axios.delete(url, { method: 'DELETE' })
        .then(resData => console.log('Deleted Post Successfully ', resData.data))
        .then(()=>{
          const updatedPosts = posts.filter(post => post.id !== postId);  
          setPosts(updatedPosts);
        })
        .catch(error => setError(error));
  }

  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
    
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
        <PostItem key={post.id} post={post} onDeleteHandler={deletePost}></PostItem>
      )}
    </div>
  )
}

export default Posts;

Some points to note here-

  1. Axios returns a Promise that resolves to a response object which has a data property containing the fetched data.
  2. With Axios default behavior is to reject every response that returns with a status code that falls out of the range of 2xx and treat it as an error.
  3. Error message gives a quick summary of the error message and the status it failed with.
  4. There is no change in ErrorMessage component. Please refer the above example to get the code for ErrorMessage component.

DELETE request using Axios With async/await - React Example

Here is the same example which uses async/await rather than using Promise with .then chaining. You can use try/catch to handle errors with async/await.

import axios from "axios";
import { useEffect, useState } from "react";
import ErrorMessage from "./ErrorMessage";
import PostItem from "./PostItem";

const Posts = () => {
  // initially empty array of posts
  const [posts, setPosts] = useState([]);
  const [error, setError] = useState();
  useEffect(()=>{
    axios.get('https://jsonplaceholder.typicode.com/posts?_limit=10')
    .then((response) => setPosts(response.data))
    .catch((error) => setError(error))
  }, []);

  const deletePost = async (postId)=> {
    console.log('In delete post', postId);
    try{
      const url = 'https://jsonplaceholder.typicode.com/posts/' + postId;
      const response = await axios.delete(url, { method: 'DELETE' });

      console.log('Deleted Post Successfully');
      const updatedPosts = posts.filter(post => post.id !== postId);  
      setPosts(updatedPosts);

    }catch(error){
      setError(error);
    }
  }

  if(error){
    return (
      <ErrorMessage message={error.message}></ErrorMessage>
    )
  }
    
  return (
    <div className="container">
      <h2 className="text-info text-center">Posts</h2>
      {posts.map((post) => 
        <PostItem key={post.id} post={post} onDeleteHandler={deletePost}></PostItem>
      )}
    </div>
  )
}

export default Posts;

There is no change in the other component PostItem so it can be used as shown in the above example.

That's all for the topic HTTP DELETE Method in React - fetch, Axios. If something is missing or you have something to share about the topic please write a comment.


You may also like

No comments:

Post a Comment