Home > Blockchain >  How to map components and ensure the component has the same attribute individually
How to map components and ensure the component has the same attribute individually

Time:05-30

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>
            }
          />
))
}
  • Related