Send Data to the Server With axios
Tags: javascript, tutorial, react, productivity
Published: 2021-06-02 04:20:42

You must be a glutton for punishment if you're here following my [post](https://dev.to/crrojas88/make-http-get-requests-with-axios-23id) on `GET` requests with axios.

![axios npm logo](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/36k73z7ceesz2jvrsi74.png)
<figcaption>Love you axios</figcaption>

As long as I have you here, let's recap on what we covered in the last post:

* We created a JSON server to store our contacts.
* Installed and imported axios to our app
* Made an HTTP `GET` request using `useEffect()` and `axios.get()`

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

const App = () => {

  // our state hooks
  const [ people, setPeople ] = useState([])
 // our new state hooks that will store our newName and newNumber field inputs.
  const [ newName, setNewName ] = useState('')
  const [ newNumber, setNewNumber ] = useState('')

  // our axios GET request
  const hook = () => {
    axios.get('http://localhost:3001/people')
    .then(response => {
      setPeople(response.data)
    })
  }

  // the useEffect function takes in 2 parameters, a function, and the number of times we want it to run.
  useEffect(hook, [])

//...
```
<figcaption>How our app looks so far</figcaption>

In order to create a new resource           for storing a contact, we're going to make an HTTP `POST` request to the _people_ URL according to [RESTful](https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services) conventions. The data for the new contact will be sent in the _body_ of the request.

```javascript
const addContact = (e) => {
  e.preventDefault()

  const nameObj = {
    name: newName,
    number: newNumber
  }

  axios.post('http://localhost3001/people', nameObj)
  .then(response => {
   setPeople(people.concat(response.data))
   setNewName('')
   setNewNumber('')
 })
}
```

The new contact returned by the backend server 
is added to the list of contacts in our app's state by using the `setPeople()` function and then resetting the `newName` & `newNumber` creation form.

In this case, since the data sent in the `POST` request is a JavaScript object, axios automatically knows to set the appropriate `application/json` value for the _Content-Type header_. How cool is that? No more typing up those pesky headers.

Take note that the `concat()` method is not changing the original state, but instead making a new copy of the list.

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

const App = () => {

  // our state hooks
  const [ people, setPeople ] = useState([])
// our new state hooks that will store our newName and newNumber field inputs.
  const [ newName, setNewName ] = useState('')
  const [ newNumber, setNewNumber ] = useState('')

  const hook = () => {
    axios.get('http://localhost:3001/people')
    .then(response => {
      setPeople(response.data)
    })
  }
  useEffect(hook, [])

  const addContact = (e) => {
  e.preventDefault()

  const nameObj = {
    name: newName,
    number: newNumber
  }

  axios.post('http://localhost3001/people', nameObj)
  .then(response => {
   setPeople(people.concat(response.data))
   setNewName('')
   setNewNumber('')
  })
 }

//...
```
<figcaption>State of our app so far...</figcaption>

Let's add some functionality to edit existing numbers if a contact `name` already exists.

```javascript
const handleSubmit = (e) => {
    e.preventDefault()

    const exists = people.find(person => person.name === newName)
    
    if(exists) {
      const person = people.find(p => p.name === newName)
      const confirmChange = window.confirm(`${newName} already exists. Replace old number with a new one?`)
      if(confirmChange) {
      const id = person.id
      const updatedPerson = {...person, number: newNumber}
      const url = `http://localhost:3001/people/${id}`

      axios
      .put(url, updatedPerson)
      .then(response => {
      setPeople(people.map(p => p.id !== id ? p : response.data))
      })
      } else {
        setPeople(people)
      }
    } else {
      addContact(e)
    } 
    setNewName('')
    setNewNumber('')
  }
```

Every line of code in the function body contains important details. Since we're using one single submit button, we're going to handle the logic in the `handleSubmit` function.

* `exists` finds if the `newName` field matches a name inside the `people` array.
* `confirmChange` sends a confirmation window to replace an existing contact.
*  If confirmed, the `if` statement block creates an `updatedPerson` object by using the [spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) and adding the new number. If not, then `setPeople` is run with the original array.
* In that same `if` block, our axios `PUT` request is called to the backend where it will replace the old object.
* The `map` method inside our `setPeople` function creates a new array by mapping every item from the old array into an item in the new array. In our example, the new array is created conditionally so that if `p.id !== id` is true, we simply copy the item from the old array into the new array. If false, then the note object returned by the server is added to the array instead.
* Outside of our nested `if` statement, if the name does not exist, then the `addContact` function is called.

And that's it! We've now successfully made a `POST` and `PUT` HTTP request with axios. Our code is looking a little bloated now so let's see if we can clean it up a little by creating a separate module that will handle backend communication in another blog post.

## Resources

* [axios](https://github.com/axios/axios)
* [Representational State Transfer](https://en.wikipedia.org/wiki/Representational_state_transfer#Applied_to_Web_services)
* [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch)
* [Spread Operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax)