메뉴 버튼을 누르면 나오는 히든 메뉴를 불러오는 기능을 구현했는데, 그 과정에서 무한 재귀가 발생해서 한참 애를 먹었다.
겨우 무한 재귀가 원인임을 파악하고... 이렇게 메뉴 버튼을 클릭하면 사이드의 메뉴가 나타나도록 코드를 짤 수 있었다.
import React, { useState } from "react";
import styled from "styled-components";
import HeaderLogoMainLogo from "./headerLogoMainLogo/HeaderLogoMainLogo";
import HeaderLogoOpenMenu from "./headerLogoOpenMenu/HeaderLogoOpenMenu";
import HeaderLogoOpenHiddenMenu from "./headerLogoOpenHiddenMenu/HeaderLogoOpenHiddenMenu";
const HeaderLogoWrap = styled.div`
width: 169px;
display: flex;
justify-content: flex-start;
align-items: center;
.visible {
width: 240px;
visibility: visible;
}
.invisible {
width: 0;
visibility: hidden;
}
`;
const HeaderLogo = () => {
const [willBeShown, setWillBeShown] = useState(false);
return (
<HeaderLogoWrap>
<HeaderLogoOpenMenu
willBeShown={willBeShown}
setWillBeShown={setWillBeShown}
/>
<HeaderLogoMainLogo />
<HeaderLogoOpenHiddenMenu
willBeShown={willBeShown}
setWillBeShown={setWillBeShown}
></HeaderLogoOpenHiddenMenu>
</HeaderLogoWrap>
);
};
export default HeaderLogo;
무한재귀가 발생했던 원인은, useState를 메뉴 버튼에 사용했기 때문이었다. 메뉴 버튼인 HeaderLogoOpenMenu는 클릭되면 HeaderLogoOpenHiddenMenu를 호출하는데, 호출된 HeaderLogoOpenHiddenMenu에서도 HeaderLogoOpenMenu가 여전히 존재해야 한다. 그래서 HeaderLogoOpenMenu에 onClick 이벤트를 걸어 HeaderLogoOpenHiddenMenu를 호출한 뒤, HeaderLogoOpenHiddenMenu에서 다시 HeaderLogoOpenMenu를 호출했더니 무한 재귀가 발생했다. 이를 해결하는 방법은 위와 같이 부모 컴포넌트인 HeaderLogo에서 willBeShown 상태를 정의해 준 뒤, 이 값이 true일 때만 HeaderLogoOpenHiddenMenu를 렌더링하도록 하는 것이다. 부모 컴포넌트인 HeaderLogo에서는 기본적으로 willBeShown의 값을 false로 각각 HeaderLogoOpenMenu, HeaderLogoOpenHiddenMenu로 전달한다. 이 때, willBeShown의 값도 바뀌어야 하므로 setWillBeShown도 함께 전달한다.
const HeaderLogoOpenMenu = ({ willBeShown, setWillBeShown }) => {
const onClickLogo = () => {
setWillBeShown(!willBeShown);
};
return (
<div onClick={onClickLogo}>
<i className="fas fa-bars"></i>
</div>
);
};
자식 컴포넌트인 HeaderLogoOpenMenu에서는 로고가 클릭되면 willBeShown의 값을 반대로 바꿔줄 것이다. 이렇게 willBeShown의 값이 true 혹은 false로 바뀌면 부모 컴포넌트가 리렌더링되고, 다시 한 번 willBeShown과 setWillBeShown이 HeaderLogoOpenMenu, HeaderLogoOpenHiddenMenu로 전달된다.
const HeaderLogoOpenHiddenMenu = ({ willBeShown, setWillBeShown }) => {
return (
<HiddenMenuWrap className={willBeShown ? "visible" : "invisible"}>
<HiddenMenuLogoWrap className={willBeShown ? "visible" : "invisible"}>
<HeaderLogoOpenMenu
willBeShown={willBeShown}
setWillBeShown={setWillBeShown}
/>
<HeaderLogoMainLogo />
</HiddenMenuLogoWrap>
<HiddenMenuGuideWrap>
<HiddenMenuGuideHome />
</HiddenMenuGuideWrap>
</HiddenMenuWrap>
);
};
willBeShown이 HeaderLogoOpenHiddenMenu로 전달되면, 이것이 true인 경우에 visible 클래스를, false인 경우에는 invisible 클래스를 로고에 부여한다. visible 클래스는 위에서 정의한 스타일대로, width값을 설정해 주고, invisible 클래스는 width가 0인 상태이다. 즉, 전달받은 willBeShown이 true라면 왼쪽에 감춰진 히든 메뉴가 드러나고, false라면 히든 메뉴를 다시 감추는 것이다.
이를 통해 무한 재귀 현상을 해결하고 클릭에 따라 나타나거나 사라지는 히든 메뉴를 만들 수 있었다.
[Clone YouTube] Interim Check(Main Page) (0) | 2021.08.30 |
---|---|
[Clone YouTube]Global Style (0) | 2021.08.19 |
[Clone YouTube] React Router (0) | 2021.08.15 |
[Clone YouTube] Contents (0) | 2021.08.13 |
[Clone YouTube] Header & Navigator (0) | 2021.08.07 |
댓글 영역