Problem with getting e.target value from an asynchronous function

I’ve got a little problem with getting value from an asynchronous function and then use it in the e.target function. I want to be able to click one of two lists (names and surnames) and then show in the div called ‘result’ the result. I read lots of articles but none of them was straight accurate to my problem ๐Ÿ™ What am I doing wrong?

async function getData() {
    let url = 'http://www.json-generator.com/api/json/get/cuSKqtKmgi?indent=2';
    try {
        let res = await fetch(url);
        return await res.json();
    } catch (error) {
        console.log(error);
    }
}

async function renderUsers() {
    const nameList = document.querySelector('.name-list')
    const surnameList = document.querySelector('.surname-list')
    let data = await getData();
    let names = '';
    let surnames = '';
    data.person.forEach(user => {
        let htmlSegment = `
                            <li>${user.name}</li>
                            `;

        names += htmlSegment;
    });
    data.person.forEach(user => {
        let htmlSegment = `
                            <li>${user.surrname}</li>
                            `;

        surnames += htmlSegment;
    });
    nameList.innerHTML = names;
    surnameList.innerHTML = surnames;
}
const chooseUser = (e) => {
    const result = document.querySelector('.result')
    const origin = e.target;
    result.textContent = origin.textContent;

}
const showUser = () => {
    const menu = document.querySelectorAll('ul li')
    menu.forEach(element => {
        element.addEventListener('click', chooseUser)
    });
}
renderUsers();
showUser()
nav{
    display: flex;
    justify-content: flex-start;
}
ul li{
    cursor: pointer;
}
 <nav>
        <ul class="name-list">
        </ul>
        <ul class="surname-list">
        </ul>
    </nav>
    <div class="result"></div>

If something is unclear feel free to ask ๐Ÿ™‚

Answer

Lots of things I would fix in this program –

  • Keep functions synchronous wherever possible
  • Functions should take arguments and return results
  • Write generic functions that can be reused
  • Using .innerHTML to build complex documents forces all of your data through the String interface
  • Error handling should not be part of your fetching function. Let the caller decide what to do

const getJSON = url =>                             // <- generic
  fetch(url).then(r => r.json())

function li(text)
{ const e = document.createElement("li")           // <- use DOM api
  e.textContent = text
  return e                                         // <- returns value
}

function appendUsers(elem, users)
{ const names = elem.querySelector(".name-list")
  const surnames = elem.querySelector(".surname-list")
  for (const u of users)
  { names.appendChild(li(u.name))                  // <- DOM api
    surnames.appendChild(li(u.surrname))
  }
}

const showUser = (elem, name) =>
  elem.textContent = name

async function main(url)
{ const nav = document.querySelector("nav")        // <- once
  const result = document.querySelector("#result") // <- once
  const data = await getJSON(url)                  // <- generic
  appendUsers(nav, data.person)                    // <- synchronous
  nav.addEventListener("click", e => {
    showUser(result, e.target.textContent)
  })
}

main("http://www.json-generator.com/api/json/get/cuSKqtKmgi?indent=2")
  .catch(console.error)                            // <- err handler
nav{
    display: flex;
    justify-content: flex-start;
}
ul li{
    cursor: pointer;
}
<nav>
    <ul class="name-list">
    </ul>
    <ul class="surname-list">
    </ul>
</nav>
<div id="result"></div>