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
Array index starts from
0
. In the final iteration, when your loop try to accessbook.characters[3].name
, it looks forname
from the fourth position in thecharacters
array and returnsundefined
.Change
To
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: