개발/react
[React] 토글 메뉴 외부 영역 클릭 시 닫기
JH._.kim
2024. 2. 20. 15:18
리액트에서 토글 메뉴를 구현하고, 메뉴 외부 영역을 클릭했을 때 메뉴가 닫히도록 구현하고자 했다.
import React, { useState, useRef, useEffect } from "react"
export const SubMenu = () => {
return (
<div className="sub-menu">
<ul className="sub-menu-list">
<li className="sub-menu-item">
<button type="button" className="btn-sub-menu">메뉴 1</button>
</li>
<li className="sub-menu-item">
<button type="button" className="btn-sub-menu">메뉴 2</button>
</li>
</ul>
</div>
)
}
export const Box = () => {
const subMenuRef = useRef<HTMLDivElement | null>(null)
const [subMenuShow, setSubMenuShow] = useState(false);
useEffect(() => {
const handleClose = (e: {target: any}) => {
if(subMenuShow && (!subMenuRef.current?.contains(e.target))) {
setSubMenuShow(false)
};
}
document.addEventListener('click', handleClose);
return () => document.removeEventListener('click', handleClose);
}, [subMenuShow])
return (
<li className="box-item">
<div className="box-area">
<div className="sub-menu-wrap" ref={subMenuRef}>
<button type="button" className="btn btn-post-manage" onClick={() => {setSubMenuShow(!subMenuShow)}}>버튼</button>
{subMenuShow && <SubMenu />}
</div>
</div>
</li>
)
}
먼저 <SubMenu>라는 토글 메뉴 컴포넌트를 만들어주었다.
그리고 useState를 통해 상태를 만들었고, subMenuShow가 true일 때 <SubMenu>가 나타나도록 했다.
useRef를 사용하여 외부영역이 아닌 버튼과 메뉴를 하나의 div에 묶어주었다.
그리고 useRef의 current에 담긴 엘리먼트가 아닌 요소가 클릭되었을 때 메뉴가 닫히도록 했다.
이벤트리스너를 제거해주지 않으면 컴포넌트가 리렌더링 될 때 마다 계속해서 이벤트리스너가 실행되므로,
컴포넌트가 언마운트될 때 removeEventListener로 이벤트를 제거해서 메모리 누수가 발생하지 않도록 했다.
참고 링크
https://yzlosmik.tistory.com/104
728x90