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