POST HTTP Request in React

Introduction

When working with APIs we oftentimes want to send data to the server for processing. For example, if we have a list of to-dos and want to add to it, perhaps through a form submission, we use POST HTTP requests to send a request with a payload for processing and potential persistence.

In this article, we will learn how to perform POST HTTP requests in React using two commonplace approaches: the Fetch API and Axios. We will also get to know how to do this in functional and class-based components.

Using the Fetch API, sending a POST HTTP request with React is as easy as:

// Using Fetch API
fetch('/myserver.endpoint', {
  method: 'POST',
  body: JSON.stringify({
    // Add parameters here
  })
  headers: {
    'Content-type': 'application/json; charset=UTF-8',
  },
})
   .then((response) => response.json())
   .then((data) => {
      console.log(data);
      // Handle data
   })
   .catch((err) => {
      console.log(err.message);
   });

Axios provides us with an elegant alternative to send HTTP POST requests:

// Using Axios - ensure you first install the package
axios.post('/myserver.endpoint', {
    // Add parameters here
  })
  .then((response) => {
    console.log(response.data);
      // Handle data
  })
  .catch((error) => {
    console.log(error);
  })

If you'd like to learn more about these approaches and how they work - please read the rest of the guide!

What is a POST HTTP Request?

As the name implies, POST requests are used to post data to an endpoint - which then typically processes it and saves it in a database. This data could come from a form, be saved in an object, or be obtained in another way - but it's typically converted into a JSON representation for the REST API to consume.

Sending HTTP requests with any verb is made simple by the Fetch API (built-in) and libraries such as Axios. The Fetch API is a built-in browser method for performing HTTP requests, whereas Axios is an external package we must install in our project before using.

Choosing between these is up to you. The Fetch API is more verbose and doesn't work with asynchronous requests, but Axios is an external dependency. Even so - many prefer working with Axios rather than the Fetch API. We'll cover both.

Both methods have advantages and disadvantages, but it is important to note that they can handle the standard HTTP verbs - POST, GET, PUT, PATCH, DELETE.

Note: As previously stated, we will learn how to perform POST requests with functional components using the Fetch API and Axios methods, and then in class-based components using the JSON Placeholder Free Fake Posts REST API.

In our instance, we'll work a list of posts that we have already fetched from a mock API. We'll create a form that takes the title and body of a new post, and once submitted, sends a POST request to the mock server for processing:

import { useState, useEffect } from 'react';

const App = () => {
   const [posts, setPosts] = useState([]);

   useEffect(() => {
      fetch('https://jsonplaceholder.typicode.com/posts?_limit=5')
         .then((res) => res.json())
         .then((data) => {
            console.log(data);
            setPosts(data);
         })
         .catch((err) => {
            console.log(err.message);
         });
   }, []);

   return (
      <>
         <div className="add-post-container">
            <form>
               <input type="text" className="form-control" />
               <textarea className="form-control" cols="10" rows="8"></textarea>
               <button type="submit">Add Post</button>
            </form>
         </div>
         <div className="posts-container">
            {posts.map((post) => {
               return (
                  <div className="post-card" key={post.id}>
                     <h2 className="post-title">{post.title}</h2>
                     <p className="post-body">{post.body}</p>
                     <div className="button">
                        <div className="delete-btn">Delete</div>
                     </div>
                  </div>
               );
            })}
         </div>
      </>
   );
};

export default App;

Let's now make the form functional so that we can add data to the post lists on our website once the form is submitted.

How To Perform POST HTTP Request in React's Functional Component

We can now perform HTTP requests in functional components thanks to the introduction of hooks in React. Previously, functional components were only used for rendering UI.

A functional component is created when a JavaScript function (either standard or ES6) returns a React element (JSX).

Rather than using the state object in the constructor method as with class-based components, we now use React hooks such as useState() to store our data before passing it into the original data.

How To Perform POST HTTP Request in React's Functional Component With Fetch API

Because the Fetch API is a built-in browser method that returns a Promise, we use the .then() and .catch() methods to handle success and failure. It also accepts a mandatory argument, which is the URL of the resource/API into which we want to POST data, as well as an argument indicating the HTTP request, which in our case is POST:

import { useState, useEffect } from 'react';

const App = () => {
   const [posts, setPosts] = useState([]);
   const [title, setTitle] = useState('');
   const [body, setBody] = useState('');
   
   // ... Fetch posts here
   
   // Handle post request
   const handleSubmit = (e) => {
      e.preventDefault();
      fetch('https://jsonplaceholder.typicode.com/posts', {
         method: 'POST',
         body: JSON.stringify({
            title: title,
            body: body,
            userId: Math.random().toString(36).slice(2),
         }),
         headers: {
            'Content-type': 'application/json; charset=UTF-8',
         },
      })
         .then((res) => res.json())
         .then((post) => {
            setPosts((posts) => [post, ...posts]);
            setTitle('');
            setBody('');
         })
         .catch((err) => {
            console.log(err.message);
         });
   };

   return (
      // ... JSX here
   );
};

export default App;

In the code above, we created a method that we'll link to the form so that it is triggered when the submit button of the form is clicked. We started by using e.preventDefault() to prevent the page from reloading when submitting the form, which is usually what you want to happen, but doesn't work as well for our demo:

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

Looking at the fetch() call, we added the URL as the first mandatory parameter, and the second parameter takes in the request method (POST), the body, and the header:

  • body - contains the data we want to send to the API endpoint, which we must stringify, turning it into a text-based JSON representation.
  • header - specifies the content type, which in our case is application/json, since our payload is represented as a JSON string:
const handleSubmit = (e) => {
   e.preventDefault();
   fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      body: JSON.stringify({
         title: title,
         body: body,
         userId: Math.random().toString(36).slice(2),
      }),
      headers: {
         'Content-type': 'application/json; charset=UTF-8',
      },
   })
};

Finally, because this method returns a Promise, we'll extract the JSON contents out of it (response of the server), and update the posts state to include the new data.

To handle errors, we also used the .catch() method:

Free eBook: Git Essentials

Check out our hands-on, practical guide to learning Git, with best-practices, industry-accepted standards, and included cheat sheet. Stop Googling Git commands and actually learn it!

const handleSubmit = (e) => {
   e.preventDefault();
   fetch({...})
      .then((res) => res.json())
      .then((post) => {
         setPosts((posts) => [post, ...posts]);
         setTitle('');
         setBody('');
      })
      .catch((err) => {
         console.log(err.message);
      });
};

Warning: Typically, you won't store and process data on the front-end like we are, but since the mock API we're working with won't actually save and return the new post - we're artificially adding it to the list it does return from the first GET request. Once the post is stored in the database - we can make another request to the back-end to supply the response to show to the user. This is also why the default behavior of the form submission is to reload the page - which would trigger the initial fetch() GET request and display the new post alongside the old ones, automatically.

How To Perform POST HTTP Request in React's Functional Component With Axios

We explained how to perform POST requests with the Fetch API in the previous section. Now, let's modify the handleSubmit() method and perform POST requests with Axios instead.

Axios is an HTTP client library that uses promises to make it easy to send asynchronous HTTP requests to REST endpoints. Because it is an external library, we must first install it in our project by running the following command in the directory of our project:

$ npm install axios

Once we've successfully installed Axios, we can proceed to perform our POST request:

const handleSubmit = (e) => {
   e.preventDefault();
   axios
      .post('https://jsonplaceholder.typicode.com/posts', {
         title: title,
         body: body,
      })
      .then((res) => {
         setPosts((posts) => [res.data, ...posts]);
         setTitle('');
         setBody('');
      })
      .catch((err) => {
         console.log(err.message);
      });
};

Looking at the code above, it's far easier and requires less syntax than the Fetch API, as we no longer need to convert to JSON, work with headers and even stringify our data. This boilerplate is abstracted away by Axios.

How To Perform POST HTTP Request in React's Class Component

POST requests in class components are handled differently than in functional components because we no longer use React hooks and instead use the state object.

A class component is an ES6 class that returns JSX and requires React extensions.

How To Perform POST HTTP Request in React's Class Component With Fetch API

The request is very similar to that of functional components. The only areas we would find some differences are when storing data in state and when using state values because we are no longer using the useState() hook:

import React, { Component } from 'react';

class App extends Component {

   constructor(props) {
      super(props);
      this.state = {
         posts: [],
      };
   }
   
   // ...   

   handleSubmit = (e) => {
      e.preventDefault();
      fetch('https://jsonplaceholder.typicode.com/posts', {
         method: 'POST',
         body: JSON.stringify({
            title: this.state.title,
            body: this.state.body,
            userId: Math.random().toString(36).slice(2),
         }),
         headers: {
            'Content-type': 'application/json; charset=UTF-8',
         },
      })
         .then((response) => response.json())
         .then((data) => {
            this.setState({ posts: [data, ...this.state.posts] });
            this.setState({ title: '' });
            this.setState({ body: '' });
         })
         .catch((err) => {
            console.log(err.message);
         });
   };

   render() {
      const { posts, title, body } = this.state;
      return (
         // ... JSX here
      );
   }
}

export default App;

This time, we no longer declare methods with the const keyword. Instead, prefix them with this. This method will be triggered when the form's submit button is clicked. Since it's a form, we started by using e.preventDefault() to prevent the page from reloading when the form is submitted:

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

Just like we learned earlier, the Fetch API takes in two parameters. One is the URL, while the second contains options like the request method (POST), body, which is the info we are posting (must be stringified), and then the headers:

handleSubmit = (e) => {
   e.preventDefault();
   fetch('https://jsonplaceholder.typicode.com/posts', {
      method: 'POST',
      body: JSON.stringify({
         title: this.state.title,
         body: this.state.body,
         userId: Math.random().toString(36).slice(2),
      }),
      headers: {
         'Content-type': 'application/json; charset=UTF-8',
      },
   })
};

Knowing this is a promise, we can now attach the .then() method to handle success and the .catch() method to handle a situation if there is an error or failure in the HTTP request.

How To Perform POST HTTP Request in React's Class Component With Axios

We have seen how to perform POST HTTP requests in class-based components. This is very similar to Axios, as all we have to do is install Axios and then replace the handleSubmit() method, so we now use Axios rather than Fetch API:

handleSubmit = (e) => {
   e.preventDefault();
   axios
      .post('https://jsonplaceholder.typicode.com/posts', {
         title: this.state.title,
         body: this.state.body,
         userId: 1,
      })
      .then((response) => {
         this.setState({ posts: [response.data, ...this.state.posts] });
         this.setState({ title: '' });
         this.setState({ body: '' });
      })
      .catch((error) => console.log(error));
};

Conclusion

In this guide, we learned how to use the two primary methods in React to perform POST HTTP requests. We also saw how they could be done in both functional and class-based components, so this article can serve us regardless of what is used in our project.

Last Updated: April 12th, 2023
Was this article helpful?

Improve your dev skills!

Get tutorials, guides, and dev jobs in your inbox.

No spam ever. Unsubscribe at any time. Read our Privacy Policy.

Joel OlawanleAuthor

Frontend Developer & Technical Writer

© 2013-2024 Stack Abuse. All rights reserved.

AboutDisclosurePrivacyTerms