Arex Speed
Arex Speed

Reputation: 177

Show hover on specific card in react

I am facing this problem. I want to show hover box on this box which is chosen. F.e when I hover on Box One I want to show Hover One, Box Two -> Hover Two. But in my example when I hover on One both are displayed. I am trying to do this with refs or e.target but always something is not as I want. Link to stackblitz: https://stackblitz.com/edit/react-hc4741?file=src/App.js

import React, { useState } from "react";
import "./style.css";
import { BooksSection, BookCard, BookCardHover } from "./Styled";

export default function App() {
  const [displayBookCardHover, setDisplayBookCardHover] = useState(false);

  const showCardHover = () => {
    setDisplayBookCardHover(true);
  };
  const hiddenCardHover = () => {
    setDisplayBookCardHover(false);
  };

  return (
    <div>
      <BooksSection>
        <BookCard
          bgColor={"#000"}
          color={"#fff"}
          onMouseEnter={showCardHover}
          onMouseLeave={hiddenCardHover}
        >
          <BookCardHover display={displayBookCardHover}>
            Hover One
          </BookCardHover>
          Box One
        </BookCard>
        <BookCard
          bgColor={"#fff"}
          color={"#000"}
          onMouseEnter={showCardHover}
          onMouseLeave={hiddenCardHover}
        >
          <BookCardHover display={displayBookCardHover}>
            Hover Two
          </BookCardHover>
          Box Two
        </BookCard>
      </BooksSection>
    </div>
  );
}

styled components

import styled from "styled-components";

export const BooksSection = styled.div`
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  width: 100wh;
`;
export const BookCard = styled.div`
  width: 50%;
  height: 500px;
  padding: 20px 0;
  background: ${props => props.bgColor};
  color: ${props => props.color};
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  position: relative;
`;

export const BookCardHover = styled.div`
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  font-size: 50px;
  background: rgba(0, 0, 0, 0.7);
  visibility: ${({ display }) => (display ? "100" : "hidden")};
`;

Upvotes: 1

Views: 3415

Answers (4)

technophyle
technophyle

Reputation: 9128

The problem is you have the exact same component with the exact same prop value in both places, so they will be shown/hidden at the same time no matter what you do to the displayBookCardHover value.

The trick is to use a separate value for each. Like this:

const [hoverIndex, setHoverIndex] = useState(-1);

...
const showCardHover = (index) => {
  setHoverIndex(index);
}

const hiddenCardHover = () => {
  setHoverIndex(-1);
}

...
<BookCard
  ...
  onMouseEnter={() => showCardHover(0)}
  ...
>
  <BookCardHover display={hoverIndex === 0}>

...

<BookCardHover display={hoverIndex === 1}>

Hope you get the idea.

On a side note, there's no "100" value for visibility prop. It's either "hidden" or "visible".

Upvotes: 2

Mohamed Mufeed
Mohamed Mufeed

Reputation: 1570

The issue with your code is - both of the BookCardHover component base their state of the display using the same reference state displayBookCardHover, so, when one changes the value of displayBookCardHover, it automatically reflect on the other. I would recommend the approch suggested by @technophyle to seperate them.

Upvotes: 0

Prabath Madushan
Prabath Madushan

Reputation: 31

import React, { useState } from "react";
import "./style.css";
import { BooksSection, BookCard, BookCardHover } from "./Styled";

export default function App() {
  const [displayBookCardHover, setDisplayBookCardHover] = useState({
  boxOneHover: false,
  boxTowHover: false
});

const showCardHover = box => {
  if (box === 1) {
     setDisplayBookCardHover(ps=>({ ...ps, boxOneHover: true }));
  } else {
     setDisplayBookCardHover(ps=>({ ...ps, boxTowHover: true }));
  }
};
const hiddenCardHover = box => {
  if (box === 1) {
     setDisplayBookCardHover(ps=>({ ...ps, boxOneHover: false }));
  } else {
     setDisplayBookCardHover(ps=>({ ...ps, boxTowHover: false }));
  }
};

return (
 <div>
  <BooksSection>
    <BookCard
      bgColor={"#000"}
      color={"#fff"}
      onMouseEnter={() => showCardHover(1)}
      onMouseLeave={() => hiddenCardHover(1)}
    >
      <BookCardHover display={displayBookCardHover.boxOneHover}>
        Hover One
      </BookCardHover>
      Box One
    </BookCard>
    <BookCard
      bgColor={"#fff"}
      color={"#000"}
      onMouseEnter={() => showCardHover(2)}
      onMouseLeave={() => hiddenCardHover(2)}
    >
      <BookCardHover display={displayBookCardHover.boxTowHover}>
        Hover Two
      </BookCardHover>
      Box Two
    </BookCard>
  </BooksSection>
 </div>
 );
}

Upvotes: 1

radeon2211
radeon2211

Reputation: 1

I think that the BookCard should be a component. Each one should have its own state. In App.js you can use BookCard and pass bgColor and color and whatever you want to customize each BookCard as props and use them in it.

Upvotes: 0

Related Questions