DIY Function APIs
Tags: javascript, react
Published: 2021-02-02 17:46:23

# Introduction
Sometimes, our applications can get really crazy. Especially when your backend API calls become abundant in numbers. Here's how I managed to organize my API calls better -- Specifically, in React!

# The Problem
When we make API calls, the most common method is a `fetch` request. Some people use `axios` (which is really great!), but I'm going to keep things mostly vanilla today. :wink:

A common fetch request, such as a `POST`, looks like this:
```js
fetch("https://some-website.com/some-api-data", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        Accept: "application/json",
        Authorization: "someRandomTokenHere-bckjhbdhkcjbdh"
    },
    body: JSON.stringify({data: {someDataKey: someDataValue}})
})
.then(resp => resp.json())
.then(resp => performSomeFunc())
.catch(error => console.log(error))
``` 

Now, I get it! Copy & Paste can be really useful here. (Thanks [Larry Tesler](https://www.bbc.com/news/world-us-canada-51567695#:~:text=%22The%20inventor%20of%20cut%2Fcopy,thanks%20to%20his%20revolutionary%20ideas.%22)! :pray: RIP). But, why do that when we could do something better? Something that could cut down on code clutter... make things pretty... like, a Function API!

### What is a function API?
Simply put -- It's an API of functions!

Check this out below. In my React project, I've created a folder under `src` called `services`. In `services` is a JavaScript file named `api.js`:

```react
export const API_ROOT = "http://localhost:3000/api/v1"

const token = () => localStorage.getItem("token");

const headers = () => {
    return {
        "Content-Type": "application/json",
        Accept: "application/json",
        Authorization: token()
    };
};

// data will be nested objects...  ex. {user: {id: ...}}

const login = data => {
    return fetch(`${API_ROOT}/login`, {
        method: "POST",
        headers: headers(),
        body: JSON.stringify(data)
    }).then(resp => resp.json());
}

const newUser = data => {
    return fetch(`${API_ROOT}/users`, {
        method: "POST",
        headers: headers(),
        body: JSON.stringify(data)
    }).then(resp => resp.json())
}

const getCurrentSession = () => {
    return fetch(`${API_ROOT}/current_session`, {
        headers: headers()
    }).then(resp => resp.json());
};

const updateUser = data => {
    return fetch(`${API_ROOT}/users/${data.user.id}`, {
        method: "PUT",
        headers: headers(),
        body: JSON.stringify(data)
    }).then(resp => resp.json());
};

const getUserList = data => {
    return fetch(`${API_ROOT}/users/${data.user.id}/list`, {
        method: "POST",
        headers: headers(),
        body: JSON.stringify(data)
    }).then(resp => resp.json())
};

const getUserListByUrl = data => {
    return fetch(`${API_ROOT}/users/public/list`, {
        method: "POST",
        headers: headers(),
        body: JSON.stringify(data)
    }).then(resp => resp.json())
};

const addToUserList = data => {
    return fetch(`${API_ROOT}/users/list/add`, {
        method: "POST",
        headers: headers(),
        body: JSON.stringify(data)
    }).then(resp => resp.json())
};

const deleteUser = user_id => {
    return fetch(`${API_ROOT}/users/${user_id}`, {
        method: "DELETE",
        headers: headers(),
    }).then(resp => resp.json());
};

const deleteItem = listitem_id => {
    return fetch(`${API_ROOT}/listitem/${listitem_id}/delete`, {
        method: "DELETE",
        headers: headers(),
    }).then(resp => resp.json())
};

export const api = {
    auth: {
        login,
        getCurrentSession,
    },
    user: {
        newUser,
        updateUser,
        deleteUser,
        getUserList,
    },
    list: {
        getUserList,
        getUserListByUrl,
        addToUserList,
        deleteItem,
    }
}
```

You'll notice right at the bottom that I've created an API / data structure containing all of our functions in organized categories. Now, we can catch a glimpse of how much cleaner this will make our code!

# `componentWillUpdate()` and Function APIs
Assuming we want to check a user's session (if they are logged in), this is what our functional component might look like:

```react
import React, {useEffect} from 'react';
import { api } from '../services/api.js'

export default function dashboard(data) {

    const validateUserSession = () => {
        // some unique code here that validates a user in your app
    }

    useEffect(() => {
        api.auth.getCurrentSession()
        .then(resp => validateUserSession())
    })

    return (
        <div>
            <p>If you're reading this, you're awesome!</p>
        </div>
    )
}
```

Wonderful! Our `useEffect` hook runs when the page loads which executes a much more drawn out process (one that we defined in our Function API). It's CLEAN, it's DRY, and it's much more readable on a team.

# Conclusion
I think this is one of the most useful methods for maintaining many API calls. Without them, it's easy to lose track of each call or even waste time typing them out or finding them somewhere else you already used them! Ahh, the headaches involved... but, I hope that you guys can take this and run with it! It makes us all better developers. :wink:

Happy Tuesday!