Home > OS >  How can I implement conditional rendering using map function?
How can I implement conditional rendering using map function?

Time:01-12

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"
              onm ouseEnter={() => {
                setIsHover(true);
              }}
              onm ouseLeave={() => {
                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

CodePudding user response:

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}
      onm ouseEnter={() => setIsHover(true)}
      onm ouseLeave={() => 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
      onm ouseEnter={() => setIsHover(true)}
      onm ouseLeave={() => 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;
  }
}

CodePudding user response:

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;
}

CodePudding user response:

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

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