Separate Modules for Backend Communication
Tags: react, javascript, productivity, tutorial
Published: 2021-06-14 18:27:39

In this (final?) installment of using axios to make HTTP requests, we've managed to make  [GET](https://dev.to/crrojas88/make-http-get-requests-with-axios-23id), [POST & PUT](https://dev.to/crrojas88/send-data-to-the-server-with-axios-5h17) requests. However, our code has started to chonkify a bit. So now I'm going to cover how to separate our backend communication into its own module.

We can start by creating a new directory called _services_ inside our _src_ folder. Create a file named _contacts.js_.

```javascript
// src/services/contacts.js

import axios from 'axios';

const baseUrl = 'http://localhost3001/people'

const getAll = () => {
    const request = axios.get(baseUrl)
    return request.then(response => response.data)
}

const create = (newObject) => {
    const request = axios.post(baseUrl, newObject)
    return request.then(response => response.data)
}

const update = (newObject, id) => {
    const request = axios.put(`${baseUrl}/${id}`, newObject)
    return request.then(response => response.data)
}

const remove = (id) => {
    const request = axios.delete(`${baseUrl}/${id}`)
    return request.then(response => response.data)
}

const contactService = { getAll, create,  update, remove }

export default contactService
```
Our module returns an object with four functions that directly return the response data by the axios methods.

_"Wait, where did remove come from? and why not call it 'delete'?"_

Well, if you've been paying attention since the [beginning](https://dev.to/crrojas88/make-http-get-requests-with-axios-23id), I mentioned we'd go through `GET`, `POST`, `PUT`, **and** `DELETE` requests. I intend to keep that promise. `delete` is a reserved JavaScript word so just don't.
![Captain America Just Don't gif](https://thumbs.gfycat.com/AlertDapperAmurstarfish-size_restricted.gif)

Let's take it step-by-step:
```javascript
const getAll = () => {
    const request = axios.get(baseUrl)
    return request.then(response => response.data)
}
```
Our modified `getAll` function still returns a promise, as the `then` method of a promise also returns a promise. Once we define the parameter of the `then` method to return `response.data`, we've managed for our `getAll` function to work. Once the HTTP request is successful, the promise returns the data as a response from the backend module.

We can now import our `contactService` module into our React App.

```javascript
import contactService from './services/contacts';
```

Our functions can be used directly from the imported `contactService` module.

```javascript
import React, { useState, useEffect } from 'react';
import contactService from './services/contacts';

const App = () => {
// ...

const hook = () => {
    contactService
    .getAll()
    .then(initialContacts => {
      setPeople(initialContacts)
    })
  }
  useEffect(hook, [])

const addContact = (e) => {
    e.preventDefault()
    
    const nameObj = {
      name: newName,
      number: newNumber
    }

    contactService
    .create(nameObj)
    .then(returnedContact => {
     setPeople(people.concat(returnedContact))
    })
    setNewName('')
    setNewNumber('')
  }

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}

      contactService
      .update(updatedPerson, id)
      .then(returnedContact => {
      setPeople(people.map(p => p.id !== id ? p : returnedContact))
      })
      } else {
        setPeople(people)
      }
    } else {
      addContact(e)
    } 
    setNewName('')
    setNewNumber('')
  }


// ...
}

export default App
```

Looking cleaner and leaner already!

We're now ready to implement our `deleteContact` function.

```javascript
const App = () => {
// ...
const deleteContact = id => {
    const person = people.find(p => p.id === id)
    const confirmDelete = window.confirm(`Delete ${person.name}?`)
if(confirmDelete) {
    contactService
    .remove(id)
    .then(() => {
        setPeople(people.filter(p => p.id !== id))
    })
     // error handling that will just print to console for now.
     .catch(error => {
      console.log(error)
    })
    setNewName('')
    setNewNumber('')
  }
}

// ...
}
export default App
```

Pretty straightforward stuff. Once our `deleteContact` function is called, we set a `person` variable to match the `id` passed. Then if `confirmDelete` is true we run our `remove` function passed from our `contactService` module. Next, we chain `.then()` which attaches a callback that is invoked when the promise is settled. Inside this callback, we filter out contacts that don't match the `id` thus causing a re-render which updates our app accordingly. Lastly a `.catch()` is chained for any error handling (for now we'll just log the error to console, I'll cover error handling in another post).

<figure>
![SpongeBob tired](https://i.kym-cdn.com/entries/icons/original/000/025/794/Screen_Shot_2018-03-28_at_11.32.59_AM.png)
<figcaption>Take a breather, you've earned it!</figcaption>
</figure>

That does it for our journey through axios HTTP requests. I hope you had as much fun as I had following along! In the spirit of keeping things simple, I omitted adding other React components as well as the passing down of props. I wanted to mainly focus on the backend logic and functionality while using axios. The beauty of this is that one could easily pass down the functions we wrote as [event handlers](https://reactjs.org/docs/faq-functions.html) to our props.

## Resources

* [axios](https://github.com/axios/axios)
* [Why React Developers Should Modularize Their Applications](https://alexmngn.medium.com/why-react-developers-should-modularize-their-applications-d26d381854c1#:~:text=A%20module%20encapsulates%20a%20set,the%20rest%20of%20the%20application.)
* [Promise.prototype.finally()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally)
* [Passing Functions as Event Handlers](https://reactjs.org/docs/faq-functions.html)