리액트로 프로젝트를 하다가, 상위 컴포넌트가 hover될 때 하위 컴포넌트를 조건부 렌더링하고 싶었다.
처음에는 JavaScript로 hover될 때와 아닐 때를 state로 만들어 조건부 렌더링을 했다!
하지만 같은 기능을 JavaScript를 쓰지 않고 CSS만으로 구현하는 법을 알게 되어 기록으로 남겨보려고 한다.
아래 GIF의 각 상자는 Item이라는 컴포넌트이다. 이 Item 컴포넌트는 Container 안에 ActionButtons와 Status 컴포넌트로 이루어져 있다.
Container가 hover되면 ActionButtons가 렌더링되고, hover되지 않은 평소에는 Status가 렌더링되게 하려고 한다.
// Container가 hover되지 않았을 때(평소에)
Item
┗ Container
┣ ❌ActionButtons(안보임)
┗ ⭕Status(보임)
// Container가 hover되었을 때
Item
┗ Container
┣ ⭕ActionButtons(보임)
┗ ❌Status(안보임)
처음에는 JavaScript로 조건부 렌더링을 구현하려고 했다.
즉 isHovered
라는 state를 만들고 Container 컴포넌트가 hover되면(onMouseEnter) isHovered
를 true로 만들고, 아니면(onMouseLeave) isHovered
를 false로 만들었다.
그리고 isHovered
가 true이면 ActionButtons를 렌더링하고, false이면 Status를 렌더링했다.
const Item = () => {
const [isHovered, setIsHovered] = useState(false);
return (
<Container
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
{isHovered ? <ActionButtons /> : <Status>{status}</Status>}
</Container>
);
};
하지만 state를 만들지 않고 CSS만으로도 조건부 렌더링을 구현할 수 있었다.
none
으로 설정하여 평소에는 안보이게 하기flex
로 설정하여 보이게 하기(ActionButtons의 display가 기존에 flex였으므로)none
으로 설정하여 안보이게 하기const Item = () => {
return (
<Container>
<ActionButtons className="hover-visible" />
<Status className="hover-hidden">{status}</Status>
</Container>
);
};
const Container = styled.div`
.hover-visible {
display: none;
}
&:hover {
.hover-hidden {
display: none;
}
.hover-visible {
display: flex;
}
}
`;
Container가 hover되면 ActionButtons 컴포넌트가 나타나고, 평소에는(hover되지 않았을 때)에는 Status 컴포넌트가 렌더링된다!
이런 문제는 CSS만으로는 해결하지 못할 줄 알았다. 그래서 지금까지 오직 CSS 효과만을 위해 JavaScript로 state를 만들어왔다. 그래서 새롭게 알게 된 방법을 꼭 기록해두고 싶었다.
다음에는 CSS로 해결할 수 있는 문제는 CSS로 해결했으면 좋겠다😆