Using Fetch in JavaScript
Published: 2020-02-04 16:45:14

Sometimes we need to get information from an API. Since the 2015 updates to JavaScript, fetch() is the best way to go about this. Below I will explain the ES6 syntax for using fetch().

```function getBooks() {
    fetch('http://localhost:3000/books')
    .then((response) => {
        return response.json();
    })
    .then((books) => {
        renderBooks(books);
    });
}```

Here we can see a function getBooks, which will communicate with an API. The first step is use fetch, followed by the Url of the API inside the parentheses. This gets us the promise from the API, but the information is not usable. We then pass the response from fetch() into the next function to get the JSON data from the promise, and finally we name the JSON data 'books' and pass it to the function renderBooks. 

```function renderBooks(books) {
    books.forEach(book => {
        renderBook(book)
    });
}```

Render books simply calls another function, renderBook, that will display each book. We pass book into this function. We then look at the HTML and find the element "list". We then target "list and create a new element called li. We set the content of this new element to be book.title, then append it to the list. We also add an event listener to li that will call the function showBookCard when li is clicked. We must pass in an empty function for this to work. If we do not pass an empty function, the event listener will run on page load, which we do not want.

```function renderBook(book) {
    const unorderedList = document.getElementById("list");
    const li = document.createElement("li");
    li.textContent = book.title
li.addEventListener("click", () => showBookCard(book))
    unorderedList.appendChild(li)
}```

Next, we have function showBookCard, which will create a display that is triggered by the event listener attached to li.

 ```function showBookCard(book) {
    const showPanel = document.getElementById("show-panel")
    showPanel.innerHTML = "";

    const coverImage = document.createElement("img")
    coverImage.src = book.img_url

    const description = document.createElement("h1")
    description.textContent = book.description

    const button = document.createElement("button")
    button.textContent = "Like"
    button.addEventListener("click", () => likeBook(book))

    const usersList = document.createElement("ul")

    book.users.forEach(user => {
        const userLi = document.createElement("li");
        userLi.textContent = user.username;
        usersList.appendChild(userLi);
    })

    showPanel.appendChild(coverImage)
    showPanel.appendChild(description)
    showPanel.appendChild(button)
    showPanel.appendChild(usersList)
}```

This function looks enormous, but is actually quite simple. We first look at the HTML to find the element "show-panel" and set it to a constant showPanel. We set its innerHTML equal to an empty string to make sure any content disappears when a user clicks away. We then create a constant called coverImage and set its source to book.img_url. We then append coverImage to showPanel. We can follow the same steps for the book description, substituting textContent for source. We then create a button called "Like" that will allow a user to like a book and attach an event listener to it that will call the function likeBook when the button is clicked. We then create an element called usersList with a "ul" tag. We then use forEach to iterate through the books users (user must be passed in), creating an "li"for each one and setting the textContent equal to their username. We then append the user to to the list. All of these elements must then be appended to showPanel.

We then come to the function likeBook, which is called when a user clicks the like button on a book card.

```function likeBook(book) {
    book.users.push(userName)
    fetch(`http://localhost:3000/books/${book.id}`, {
        method: "PATCH",
        headers: {
            "Content-Type": "application/json",
            Accept: "application/json"
        },
        body: JSON.stringify({users: book.users})
    })
    .then(res => res.json())
    .then(likedBook => showBookCard(likedBook));
}```

This function accepts book as an argument. It then pushes the current user into the book's array of users. It then uses fetch to send a patch request to our API. A PATCH request updates only some of an object, rather than replacing everything like a PUSH request,. We use headers and a body tag to tell the API what kind of data it will be receiving and sending. We then convert the response to JSON and pass it to likedBook and showBookCard, which will update the DOM to reflect changes to the API.