Currently I have a map function that render a serial of image, and I realized that they share the same hover
state, which means they will perform the same action when hovered. Is there are any standard practice to map duplicate components while assigning them unique/individual properies?
{itemData.map((item) => (
<ImageListItem key={item.img}>
<img
src={item.img}
alt={item.title}
loading="lazy"
onm ouseOver={() => {setHover(true)}}
onm ouseOut={() => {setHover(false)}}
style={{ transform: hover ? 'scale(1.5, 1.5)' : null }}
/>
<ImageListItemBar
title={item.title}
subtitle={item.author}
actionIcon={
<IconButton
sx={{ color: 'rgba(255, 255, 255, 0.54)' }}
aria-label={`info about ${item.title}`}
>
<InfoIcon />
</IconButton>
}
/>
CodePudding user response:
You should use a component, which create a unique state for each element, i wrote an easy to understand example.
import React, { useState } from "react"
const items = [
{
title: 'Card1',
price: 100
},
{
title: 'Card2',
price: 50
},
{
title: 'Card3',
price: 200
},
]
export default function App() {
return (
<>
{
items.map(element => {
return(
<Card {...element}/>
)
})
}
</>
)
}
function Card({title, price, key}) {
const [isHovered, setHover] = useState(false)
return (
<>
<div
key={key}
onm ouseOver={() => {setHover(true)}}
onm ouseOut={() => {setHover(false)}}
>
<div>
{title}
</div>
<h3>
{
isHovered && price
}
</h3>
</div>
</>
);
}
I made the card price to show if hovered so you can see it works on each individual component.
Code sandbox if you want to check it out.
CodePudding user response:
To provide unique properties, you need to have something that uniquely identifies your image component and use it to manage your state. In your case, your state hover
should be an array
or an object
, not a boolean
. Since you are using item.img
as a key, I assume it is unique and hence it can help in your state management like this:
const [hover, setHover] = useState({});
{itemData.map((item) => (
<ImageListItem key={item.img}>
<img
src={item.img}
alt={item.title}
loading="lazy"
onm ouseOver={() => setHover({...hover, [item.img]: true})}
onm ouseOut={() => setHover({...hover, [item.img]: false})}
style={{ transform: hover ? 'scale(1.5, 1.5)' : null }}
/>
<ImageListItemBar
title={item.title}
subtitle={item.author}
actionIcon={
<IconButton
sx={{ color: 'rgba(255, 255, 255, 0.54)' }}
aria-label={`info about ${item.title}`}
>
<InfoIcon />
</IconButton>
}
/>
))
}