adding key to map function is not working - javascript

I am currently trying to add a key to my map. However, when I try and give it an index, it then shows up with persons as undefined. Where it was working before. Here is what I have done.
<div className='UserAdminCardsGrid'>
{personValues.map(person, index =>
<div key={index} className="UserAdminCard Card">
<b>Name:</b>
<div>{person.name}</div>
<b>ID:</b>
<div>{person.id}</div>
</div>
)}
</div>

It is a wrong syntax
personValues.map(person, index =>
Wrap the arguments in parentheses
personValues.map((person, index) =>

Add parenthesis in the arrow function:
<div className='UserAdminCardsGrid'>
personValues.map((person, index) =>
<div key={index} className="UserAdminCard Card">
<b>Name:</b>
<div>{person.name}</div>
<b>ID:</b>
<div>{person.id}</div>
</div>
)}
</div>

Wrap your argument in parenthesis or use object id
wrapping and using map function index
personValues.map((person, index) =>
or use object id as a key (Recommended to use)
{personValues.map(person =>
<div key={person.id} className="UserAdminCard Card">
<b>Name:</b>
<div>{person.name}</div>
<b>ID:</b>
<div>{person.id}</div>
</div>
)}
Index as a key is an anti-pattern
It may break your application and display the wrong data!
refer to Index as a key is an anti-pattern
article for better understanding.

<div className='UserAdminCardsGrid'>
{personValues.map(({id, name}) =>
<div key={id} className="UserAdminCard Card">
<b>Name:</b>
<div>{name}</div>
<b>ID:</b>
<div>{id}</div>
</div>
)}
</div>

Related

Mapping over 2 arrays

I have 2 arrays of objects: meeting and room and a Card component with some fields to be completed by them.
I tried to map over the arrays in order to access the elements from both of them at the same time but it returns the Card component six times(the number of the elements in the array of Room)
<div className="topCards">
{room.map((dataObj) => {
return (
<div>
{meeting.map((meetObject) => {
return (
<div className="item">
<Card3
className="card3"
teamName={meetObject.name}
roomName={dataObj.name}
time={dataObj.time}
data={dataObj.data}
capacity={dataObj.capacity}
/>
</div>
);
})}
</div>
);
})}
</div>
So, my question is how can I return the Card element with elements from both cards
What let you think that it would work like that?
Just use the index parameter of Array.prototype.map
<div className="topCards">
<div>
{meeting.map((meetObject, i) => {
return (
<div className="item">
<Card3
className="card3"
teamName={meetObject.name}
roomName={dataObj[i].name}
time={dataObj[i].time}
data={dataObj[i].data}
capacity={dataObj[i].capacity}
/>
</div>
);
})}
</div>
</div>

React Nested Foreach on Return

Trying to use nested foreach in React.
But not working at all;
return (
{category.map((item, i) => (
<div className="col-sm-12">
<h5>{item.title}</h5>
</div>
item.data.map((it, iv) => (
<div class="col-6">
<ProductCard {...it} />
</div>
))
))}
)
You are using .map higher order function
you need to wrap in in fragment so React Will know that it's a JSX or wrap it on div
Introduction to JSX
Learn Fragment React
return (
<>
{category.map((item, i) => (
<div className="col-sm-12">
<h5>{item.title}</h5>
</div>
item.data.map((it, iv) => (
<div class="col-6">
<ProductCard {...it} />
</div>
))
))}
</>
)
if you want to render nested array maybe it will work
return (
<> // Put Wrapper
{category.map((item, i) => (
<> // put an empty fragment to contain title div and another map
<div key={i} className="col-sm-12"> // dont forget to put key props
<h5>{item.title}</h5>
</div>
{item.data.map((it, iv) => ( // wrap another map on '{}' because it inside jsx
<div key={iv} class="col-6"> // dont forget to put key props
<ProductCard {...it} />
</div>
)}
</>
)}
</>
)
you can also change <> to div or any if you want to style it. And dont put // comment on jsx, it just my mark to explain this code

Cards inside the grid-container: each child in a list should have a unique "key" prop

What I`m doing wrong?It also says: "Check the render method of Card" , which is here:
<div className="grid-container">
{pokemonData.map((pokemon, i) => {
console.log(pokemon.id) // unique numbers are here
return <Card key={pokemon.id} pokemon={pokemon} />
})}
</div>
Card component itself:
function Card({ pokemon }) {
return (
<div className="card">
<div className="card__image">
<img src={pokemon.sprites.front_default} alt="Pokemon" />
</div>
<div className="card__name">
{pokemon.name}
</div>
<div className="card__types">
{
pokemon.types.map(type => {
return (
<div className="card__type" style={{backgroundColor: typeColors[type.type.name]}}>
{type.type.name}
</div>
)
})
}
</div>
<div className="card__info">
<div className="card__data card__data--weight">
<p className="title">Weight:</p>
<p>{pokemon.weight}</p>
</div>
<div className="card__data card__data--height">
<p className="title">Height:</p>
<p>{pokemon.height}</p>
</div>
<div className="card__data card__data--ability">
<p className="title">Abilities:</p>
{/* {console.log(pokemon.abilities)} Temporary for dev puprose */}
{pokemon.abilities.map(ability => <p>{ability.ability.name}</p>
)}
</div>
</div>
</div>
);
}
export default Card;
You can use the index of the array may be your data is having some kind of duplicate. It is recommended that you pass a key prop whenever you are returning a list.
<div className="grid-container">
{pokemonData.map((pokemon, i) => {
console.log(pokemon.id) // unique numbers are here
return <Card key={i} pokemon={pokemon} />
})}
</div>
Equally, check this segment of card components.
{
pokemon.types.map((type,i) => {
return (
<div key={i} className="card__type" style={{backgroundColor:
typeColors[type.type.name]}}>
{type.type.name}
/div>
)
})
}
And
<div className="card__data card__data--ability">
<p className="title">Abilities:</p>
{/* {console.log(pokemon.abilities)} }
{pokemon.abilities.map((ability, i) => <p key={i}>{ability.ability.name}
</p>
)}
</div>
Previous answer will solve your problem. However, for your info, I would also like to add here.
For React a key attribute is like an identity of a node/element/tag which helps React to identify each item in the list and apply reconciliation correctlyon each item. Without a key React will render your component but may cause issue when you re-order your list.
React recommends to use id of the data instead of index number. However, if your list does not re-orders/ sorts or do not have id then you can use index.
You can read more here:
https://reactjs.org/docs/lists-and-keys.html
Change this:
<div className="card__types">
{
pokemon.types.map(type => {
return (
<div className="card__type"
style={{backgroundColor:typeColors[type.type.name]}}
>
{type.type.name}
</div>
)
})
}
</div>
to:
<div className="card__types">
{
pokemon.types.map((type, key) => {
return (
<div key={key} className="card__type"
style={{backgroundColor:typeColors[type.type.name]}}
>
{type.type.name}
</div>
)
})
}
</div>
and:
{pokemon.abilities.map(ability => <p>{ability.ability.name}</p>
to:
{pokemon.abilities.map((ability,key) => <p key={key} >{ability.ability.name}</p>

Passing of Props in ReactJS

Following is my JSX code in a React component which is working fine and currently in use, but in most of React blog posts they are also de structuring an object. My query is - do we have any extra benefit of modifying the code to Version 2 or this is just fine.
First Version (currently in use) -
const CartItems = ({ items }) => items.length ? items.map((x, i) => (
<div key={x.id} className={`cart-item-${i}`}>
<div className="card ">
<div className="cart-item-img">
<img src={x.url} alt={x.altText} className="img" />
</div>
<div className="cart-item-desc">
<h3 className="title">{x.title}</h3>
<p className="text">{x.shortDesc}</p>
</div>
<div className="cart-item-action">
<button className="add">+</button>
<button className="subtract">-</button>
<button className="remove">X</button>
</div>
</div>
</div>)) : []
2nd Version -
const CartItems = ({ items }) => items.length ? items.map((x, i) => {
const {
id,
url,
altText,
title,
shortDesc
} = x;
return (
<div key={id} className={`cart-item-${i}`}>
<div className="card ">
<div className="cart-item-img">
<img src={url} alt={altText} className="img" />
</div>
<div className="cart-item-desc">
<h3 className="title">{title}</h3>
<p className="text">{shortDesc}</p>
</div>
<div className="cart-item-action">
<button className="add">+</button>
<button className="subtract">-</button>
<button className="remove">X</button>
</div>
</div>
</div>)
}) : []
The benefits are mostly aesthetic and subjective, so if you prefer the first one, more power to you and nothing that says you need to change it.
My personal view on the two snippets you posted: I tend to avoid direct returns from arrow functions because I'll oftentimes need to add a log or something else and having to convert back and forth eventually wears on you. This has little to do with the destructuring though, other than destructuring forces you to have a function body and explicit return.

ReactJS - How to setSate in a map function

I got an object with another object inside and I need to render the DOM like this:
Event
Tickets 1
Lot 1
Name
Lot 2
Name
Lot 3
Name
Ticket 2
Lot 1
Name
Lot 2
Name
{ this.state.dates.map((date, i) =>
<span className="event-date" key={i}>
{ date.date }
</span>
this.setState({tickets: date.tickets}) //Here, I need to update an object to map in another place
)}
./src/pages/Event/Event.js
Syntax error: D:/YEAPPS/marketplace/pwa/src/pages/Event/Event.js: Unexpected token, expected , (54:32)
Click to see the object
Do not call setState from within a render function, it will cause unnecessary rerenders, i.e. do not update the state with your tickets here
Set up your state within the component using other lifecycle hooks, e.g. componentDidMount, then simply map over your this.state.tickets.map(), or as you are already doing, this.state.dates.map()
I was able to solve like this:
{
this.state.tickets.map((ticket, i) => (
<div key={i}>
<div className="row">
<div className="col">
<h3 className="ticket-name">{ ticket.name }</h3>
</div>
</div>
{ticket.lot.map((lot, j) =>
<div className="row" key={i}>
<div className="col-8">
<h5 className="lot-name">{ lot.name }</h5>
<h6 className="lot-price">
R$ { lot.price.replace('.', ',') } <br />
<small>(R$ { lot.price.replace('.', ',') } + R$ { lot.price_tax.replace('.', ',') })</small>
</h6>
</div>
<div className="col-4">
<ChooseQuantity />
</div>
</div>
)}
<hr />
</div>
)
)
}

Categories

Resources