Search code examples
javascriptdomfetch-apidom-manipulation

How do I update the DOM using JavaScript fetch method to filter user data from API?


I am looking to GET Data from API and display in HTML page using JavaScript fetch function. The JavaScript codes are detailed below. I can read the console.log of the user data from API. However, nothing is displayed on the HTML page as expected.


    <script>
      fetch('https://dummyjson.com/user')
        .then(response => response.json())
        .then(data => console.log(data));
    </script>

I can't seem to figure out what is missing.

Screenshot 1: Data API

I have added a loop function to retrieve and filter the API data and insert the result into HTML tag as detailed below:

    <script>
      fetch('https://dummyjson.com/user')
        .then(result => {
          return result.json();
        })
        .then(data => console.log(data))
        .then(data => {
          data.forEach(user => {
            const show = `<p>${user.firstName}</p>`;
            let html = document.querySelector('item');
            html.insertAdjacentHTML('after begin', show);
          });
        });
    </script>

Screenshot 2: Console.log results

Expected result should have been the first names (firstName) of all the user.

When the code runs, output does not display the expected result in the HTML page. The console log does not show any errors. Simply a blank page.

Complete Code Below:


<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <style>
          body {
        background: transparent;
        color: #2c0493;
        padding: 44px;
        margin: 0;
        height: 100vh;
        align-items: center;
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen,
          Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
      }

      h3,
      h2 {
        margin: 0;
      }
    </style>
  </head>
  <body>
    <h2 id="header">GET Data from API</h2>
    <h3>And display in HTML with JavaScript</h3>
    <hr />
    <div id="item"></div>
    <script>
      fetch('https://dummyjson.com/user')
        .then(result => {
          return result.json()
        })
        .then(data => console.log(data))
        .then(data => {
          data.forEach(user => {
            const show = `<p>${user.firstName}</p>`
            let html = document.querySelector('item')
            html.insertAdjacentHTML('afterbegin', show)
          });
        });
    </script>
  </body>
</html>

More Screenshots here:

Screenshot 3: No HTML output

Expected output:

Screenshot 4: Expected output


Solution

  • Firstly, lets address the issues in your code

    1. .then(data => console.log(data)) means the next .then receives undefined as the argument
    2. the data is not an array, the array is data.users
    3. when getting an id in .querySelector, since it's CSS syntax, you need a # in the selector, e.g. #item
    4. in .insertAdjacentHTML the first argument is one of beforebegin|afterbegin|beforeend|afterend ... there is no space in this value

    One thing to note, since you use .afterbegin the list will be shown in reverse order to the data you receive - that may be your intention, if not, you would use beforeend in .insertAdjacentHTML

    Fixing your code, so it works:

    fetch('https://dummyjson.com/user')
      .then(result => result.json())
      .then(data => {
        console.log(data);
        return data;
      }) // 1. keep the data flowing in the chain
      .then(data => {
        data.users.forEach(user => { // 2. data.users is the array you are after
          const show = `<p>${user.firstName}</p>`;
          let html = document.querySelector('#item'); // 3. note the `#`
          html.insertAdjacentHTML('afterbegin', show); // 4. no space in afterbegin
          // note, this will display users in reverse order w.r.t. data.users
        });
      })
    <p id="item"></p>

    Let's do modern version, note the async function would not be needed in a <script type="module"> since that allows top level await

    async function getData() {
      const target = document.querySelector('#item');
      const result = await fetch('https://dummyjson.com/user');
      const data = await result.json();
      console.log(data);
      // remove the this     .reverse() below if you didn't mean to reverse the order
      const html = data.users.reverse().map(({firstName}) =>`<p>${firstName}</p>`).join("");
      target.insertAdjacentHTML('afterbegin', html);
    }
    getData();
    <p id="item"></p>