Passing State data to other component

Viewed 35

I currently have a child component MoodCard which is being rendered in parent component MoodPage.

I have a State Hook in the parent component const [isHover, setIsHover] = useState(false) which toggles between true or false when the MoodCard is hovered over.

In the MoodCard component, I have a conditional {isHover && ( <div className="play-button-container"> <i className="fas fa-play"></i> </div>)} which is suppose to display an icon on the MoodCard if isHover is set to true.

However I need to pass this isHover over to the MoodCard component so it works in the conditional.

The error I'm getting is: 'isHover' is not defined no-undef. I've tried passing it as props but I don't think I have the right idea on how to do so.

Sidenote: I need this to be an individual behaviour for each rendered MoodCard. So would it be better to put this logic in the mapped MoodCard component instances?

Here is the full code:

MoodCard.js

import "./MoodCard.scss";
import MoodPage from "../pages/MoodPage";

export default function MoodCard(props) {
  return (
    <button
      className="mood-card"
      onClick={props.onClick}
      onMouseEnter={props.onMouseEnter}
      onMouseLeave={props.onMouseLeave}
    >
      <figure
        style={{ backgroundImage: `url('${props.backgroundImage}')` }}
      ></figure>
      <h1>{props.name}</h1>
      {isHover && (
        <div className="play-button-container">
          <i className="fas fa-play"></i>
        </div>
      )}
    </button>
  );
}

MoodPage.js


const MoodCardInfo = [
  {
    name: "Rain",
    image: "https://wallpaperaccess.com/full/164284.jpg",
    sound: rain,
  },

  {
    name: "Ocean Waves",
    image: "https://wallpapercave.com/wp/wp2544960.jpg",
    sound: ocean,
  },

  {
    name: "Thunder",
    image: "https://wallpapercave.com/wp/wp2544960.jpg",
    sound: "thunder",
  },
];

export default function MoodPage() {
  const [isHover, setIsHover] = useState(false);

  useEffect(() => {
    console.log(isHover);
  });

  return (
    <>
          <section className="mood-row">
            {MoodCardInfo.map((info) => (
              <>
                <MoodCard
                  name={info.name}
                  backgroundImage={info.image}
                  onClick={() => setCurrentSound(info.sound)}
                  onMouseEnter={() => setIsHover(true)}
                  onMouseLeave={() => setIsHover(false)}
                />
              </>
            ))}
          </section>
        </div>
      </div>
    </>
  );
}
2 Answers

just do it like this:

<section className="mood-row">
            {MoodCardInfo.map((info) => (
              <>
                <MoodCard
                  name={info.name}
                  backgroundImage={info.image}
                  onClick={() => setCurrentSound(info.sound)}
                  onMouseEnter={() => setIsHover(true)}
                  onMouseLeave={() => setIsHover(false)}
                  isHover={isHover}
                />
              </>
            ))}
          </section>

////then you need to do this:

export default function MoodCard(props) {
  return (
    <button
      className="mood-card"
      onClick={props.onClick}
      onMouseEnter={props.onMouseEnter}
      onMouseLeave={props.onMouseLeave}
    >
      <figure
        style={{ backgroundImage: `url('${props.backgroundImage}')` }}
      ></figure>
      <h1>{props.name}</h1>
      {props.isHover && (
        <div className="play-button-container">
          <i className="fas fa-play"></i>
        </div>
      )}
    </button>
  );
}

you can use an id for each card info as follow:

const MoodCardInfo = [
  {
    name: "Rain",
    image: "https://wallpaperaccess.com/full/164284.jpg",
    sound: rain, 
    id:0
  },

  {
    name: "Ocean Waves",
    image: "https://wallpapercave.com/wp/wp2544960.jpg",
    sound: ocean,
    id:1
  },

  {
    name: "Thunder",
    image: "https://wallpapercave.com/wp/wp2544960.jpg",
    sound: "thunder",
    id:2
  },
];

then instead of enabling isHover as a boolean, set the id of the hovered item

const [hoverId, setHoverId] = useState(-1);

and finally, pass it to the child component:

<MoodCard
                  name={info.name}
                  backgroundImage={info.image}
                  cardId={info.id}
                  hoverId = {hoverId}
                  onClick={() => setCurrentSound(info.sound)}
                  onMouseEnter={() => setHoverId(true)}
                  onMouseLeave={() => setHoverId(-1)}
                />

I am not sure that what you want to do in the child component, but you can compare the card id with the hoverId and if their equal, you can do whatever you want. also, having useEffect without any condition is not correct, use this instead:

useEffect(() => {
    console.log(isHover);
  }, [hoverId]);
Related