🛠️ Dota Heroes: Making the hero page robust

Hey ,

I'm thrilled to help you learn JavaScript. Unfortunately, you've landed on a page where you cannot access with your current purchase.

Please upgrade (use this link) access this content.

I'm super eager to help you learn more!

🛠️ Dota Heroes: Making the hero page robust

So far, we used the hero’s name to fetch the image, description, and the hero’s abilities. This approach works for Axe, but it doesn’t work for some heroes.

One example is Shadow Fiend.

Shadow Fiend in the heroes list page.

Shadow Fiend is also called Nevermore. You can see both Shadow Fiend and Nevermore in the response from the heroes endpoint.

Shadow fiend is also called Nevermore.

The lores endpoint and the hero_abilities use nevermore instead of shadow_fiend. This tells us we can’t use Shadow Fiend in the API. We need to use Nevermore.

Lores endpoint uses Nevermore.
Hero abilities endpoint uses Nevermore.

But if we use nevermore, we don’t get the Hero’s image…

Nevermore image not showing up.

Why? Because we checked the heroes endpoint for Shadow Fiend! (localized_name contains Shadow Fiend).

Checked for localized name instead of the hero's name.

To get the image, we need to check against Nevermore instead.

Robustness for Hero Image

Nevermore is located in the hero’s name attribute.

Shadow fiend is also called Nevermore.

To get nevermore, we can get the hero’s name property and remove the npc_dota_hero_ part. We can remove it by replacing that part with an empty string.

zlFetch(`${dotaApi}/constants/heroes`)
  .then(response => {
    const heroes = Object.values(response.body).map(hero => {
      const name = hero.name.replace('npc_dota_hero_', '')
      console.log(name)
  })
Obtained nevermore from the heroes endpoint.

We’ll put this value into the formatted data. We’ll call this npcHeroName to make things clear.

zlFetch(`${dotaApi}/constants/heroes`)
  .then(response => {
    const heroes = Object.values(response.body).map(hero => {
      return {
        name: hero.localized_name,
        npcHeroName: hero.name.replace('npc_dota_hero_', ''),
        attackType: hero.attack_type.toLowerCase(),
        primaryAttribute: hero.primary_attr,
        roles: hero.roles.map(role => role.toLowerCase()),
        image: `https://api.opendota.com${hero.img}`
      }
      // ...
    })

We can now find nevermore from the list of heroes.

zlFetch(`${dotaApi}/constants/heroes`)
  .then(response => {
    const heroes = Object.values(response.body).map(hero => {
      return {
        name: hero.localized_name,
        npcHeroName: hero.name.replace('npc_dota_hero_', ''),
        attackType: hero.attack_type.toLowerCase(),
        primaryAttribute: hero.primary_attr,
        roles: hero.roles.map(role => role.toLowerCase()),
        image: `https://api.opendota.com${hero.img}`
      }
    })
    const hero = heroes.find(h => h.npcHeroName() === heroName)
    heroImageEl.src = `${hero.image}`
  }
Shadow fiend image shows up.

But the hero’s name is not Nevermore. It is Shadow Fiend. We need to insert Shadow Fiend into the DOM instead. We can do this by setting the textContent after we found the hero.

zlFetch(`${dotaApi}/constants/heroes`)
  .then(response => {
    const heroes = Object.values(response.body).map(/* ... */)
    const hero = heroes.find(h => h.npcHeroName === heroName)
    // Set the hero's name
    heroNameEl.textContent = hero.name
    heroImageEl.src = `${hero.image}`
  })
  .catch(console.log)

At this point, we can remove the capitalize function since we no longer use it.