skip to Main Content

I’m working on a Library Express App and I’m using fake data to easily display the values on screen.

const PopularBooks = [
  {
    id: 1,
    title: "Harry Potter",
    characters: [
      {
        id: 1,
        name: "Harry Potter",
      },
      {
        id: 2,
        name: "Hermione",
      },
      {
        id: 3,
        name: "Ron",
      },
    ],
  {
    id: 2,
    title: "Lord of the Rings",
    characters: [
      {
        id: 4,
        name: "Frodo",
      },
      {
        id: 5,
        name: "Legolas",
      },
      {
        id: 6,
        name: "Gandalf",
      },
    ],
  },
];

I’m able to display everything just fine except I’m having trouble getting character names to show.

    <div class="description">
      <h1><%= book.title %></h1>
    </div>
  </div>
  <div class="data-m1">
    <h4>Characters</h4>
    <div class="characters">
      <% for (let i = 1; i < 4; i++) { %>
      <div class="portrait">
        <img class="book-c" src="/images/book-c-1.png" alt="book" />
        <p><%= book.characters[0].name %></p>
      </div>
      <% } %>
    </div>
  </div>

When I put <p><%= book.characters[0].name %></p> it shows Harry Potter three times. But when I change the [0] to [i] so that it will dynamically display everyone’s name, it gives me this error: Cannot read properties of undefined (reading 'name'). I’m wondering if there is a better way to map it out because I can’t seem to find any.

And here is how I got the value of book in case you’re wondering.

router.get("/books/:title", function (req, res, next) {
  const bookId = parseInt(req.params.title);
  const book = data.PopularBooks.find((book) => book.id === bookId);
  res.render("books", { book });
});

2

Answers


  1. Array index starts from 0. In the final iteration, when your loop try to access book.characters[3].name, it looks for name from the fourth position in the characters array and returns undefined.

    Change

     <% for (let i = 1; i < 4; i++) { %>
    

    To

     <% for (let i = 0; i < 3; i++) { %>
    
    Login or Signup to reply.
  2. As mentioned in Mamun@‘s answer, you have an off-by-one issue in your loop. However, instead of fixing that, I would instead encourage you to use forEach, so that you or anyone else who reads the code dosen’t have to worry about handling indexes at all.

    Therefore improving readability since by using it, you focus on what you want to do with each element rather than how to iterate through them:

    <div class="characters">
      <% book.characters.forEach(character => { %>
      <div class="portrait">
        <img class="book-c" src="/images/book-c-1.png" alt="book" />
        <p><%= character.name %></p>
      </div>
      <% }); %>
    </div>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search