0

I made 5 blocks and want to make the letters on each block thick when the mouse is hover. I made isHover state and changed the thickness of the writing according to the state, but the problem is that the thickness of all five changes. I think I can solve it by using conditional rendering, but I don't know how to use it. Of course, it can be implemented only with css, but I want to implement it with conditional rendering because I am practicing the code concisely.

import "./styles.css";
import styled from "styled-components";
import { useState } from "react";

export default function App() {
  const array = [
    { id: "1", title: "ABC" },
    { id: "2", title: "DEF" },
    { id: "3", title: "GHI" },
    { id: "4", title: "JKL" },
    { id: "5", title: "MNO" }
  ];

  const [isHover, setIsHover] = useState(false);

  return (
    <Head isHover={isHover}>
      <div className="header">
        {array.map((content, id) => {
          return (
            <div
              className="header__title"
              onMouseEnter={() => {
                setIsHover(true);
              }}
              onMouseLeave={() => {
                setIsHover(false);
              }}
            >
              {content.title}
            </div>
          );
        })}
      </div>
    </Head>
  );
}

const Head = styled.div`
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;

  .header {
    display: inline-flex;
    border: 1px solid black;
    box-sizing: border-box;
  }

  .header__title {
    border: 1px solid red;
    padding: 5px 10px;
    font-weight: ${(props) => (props.isHover ? "700" : "400")};
  }
`;

codesandbox

https://codesandbox.io/s/aged-cherry-53pr2r?file=/src/App.js:0-1170

3
  • You're over thinking it. Just set the font inside the handler callback. Commented Jan 12, 2023 at 5:06
  • 2
    Why use JS/React for this at all? Just use CSS Commented Jan 12, 2023 at 5:07
  • Using :hover is the best way to do this, but if you do need to know how to do it in React/Styled: change the div with .header__title to a separate SC, remove the hover prop from the parent component, and only pass it to that one. (Also don't forget to pass a unique key to each element returned by your map — probably content.title). Commented Jan 12, 2023 at 5:16

3 Answers 3

3

The problem is that you are using the same state for all the 5 blocks. There are multiple approaches you could take to solve this problem.

1. Multiple states

You could create 5 different isHover<N> states (maybe a single one, but as an array)

2. Component extraction

You could just extract out a component for each entry in array and do state management in that component.

function App() {
  const array = [...];

  return (
    <Head>
      <div className="header">
        {array.map((content, id) => (
          <HeaderTitle key={content.id} content={content} />
        )}
      </div>
    </Head>
  );
}

function HeaderTitle({ content }) {
  const [isHover, setIsHover] = useState(false);
  return (
    <StyledHeaderTitle
      isHover={isHover}
      onMouseEnter={() => setIsHover(true)}
      onMouseLeave={() => setIsHover(false)}
    >
      {content.title}
    </StyledHeaderTitle>
  );
}

const StyledHeaderTitle = styled.div`
  font-weight: ${(props) => (props.isHover ? "700" : "400")};
`

3. Using style prop

Directly apply the font weight using the style prop (An extension to approach 2)

function HeaderTitle({ content }) {
  const [isHover, setIsHover] = useState(false);
  return (
    <StyledHeaderTitle
      onMouseEnter={() => setIsHover(true)}
      onMouseLeave={() => setIsHover(false)}
      style={{ fontWeight: isHover ? "700" : "400" }}
    >
      {content.title}
    </StyledHeaderTitle>
  );
}

4. CSS

CSS already allows you to track hover states over different elements and you don't need to manually track it in javascript.

.header__title {
  border: 1px solid red;
  padding: 5px 10px;
  font-weight: 400;

  &:hover {
    font-weight: 700;
  }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thank you all the way you wrote it down was helpful!!
Which one would you personally use @vighnesh153?
I would use the 4th one (CSS or styled-components). Reason being we don't need to use javascript for stuff that can be done without it.
1

There's no need to use React state and event listeners here, you can do it all in CSS instead:

.header__title {
  border: 1px solid red;
  padding: 5px 10px;
  font-weight: 400;
}

.header__title:hover {
  font-weight: 700;
}

Comments

1

Just add this pseudo class and you're good to go

.header__title:hover {
font-weight: 700;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.