구현목표
메뉴 버튼 클릭시 하단에 작은 메뉴 목록이 나오는 팝업 모달창 구현
모달창 외부 클릭시 모달창이 닫히도록 구현
그리고 (모달창 외부에 위치한) 메뉴버튼 재클릭시에도 모달창이 닫히도록 구현
문제 발생
그런데 1차 구현을 하고나서 생각지 못한 문제가 발생되었다!!...
팝업 모달창을 on/off 하는 메뉴(토글) 버튼이 모달창을 없애는 외부 영역에 위치하다보니
메뉴 버튼이 아닌 메뉴 모달창 외부 영역을 클릭하면 정상적으로 모달창을 닫을 수 있지만,
모달창 영역 외부에 위치한 메뉴 버튼 클릭시에는
모달창이 꺼지지 않고 다시 창이 뜨는 에러 현상 발생
처음에는 어떻게 접근할지 검색을 해보며 고민..
애초에 ref 값을 통해 모달창 영역을 기준으로 외부 영역을 설정하였으므로
그러면 해당 버튼에도 ref 값을 설정해주면
기준 영역을 모달창 뿐만 아니라 메뉴 버튼까지 인정해줄 수 있겠다는 논리로 접근 시도
=> 메뉴 모달창 바깥을 누르면 정상적으로 모달창이 닫힘
=> 모달창이 펼쳐진 상태에서 모달창 바깥 영역인 메뉴 버튼을 눌러도 모달창이 닫혔다가 다시 열리지 않고 정상적으로 닫히게 구현 완료
코드
...
const MenuModal = ({ setMenuModal, menuRef }) => {
const outsidemenuRef = useRef();
useEffect(() => {
const clickOutsideMenu = (e) => {
if (
//
outsidemenuRef.current &&
!outsidemenuRef.current.contains(e.target) &&
menuRef.current &&
!menuRef.current.contains(e.target)
) {
setMenuModal(false);
}
};
// 확인해보면 메뉴모달창 내부 클릭시 etarget : true
// 메뉴모달창 외부 클릭시 etarget : false
// 즉 기준이 되는 요소 클릭시 true, 기준 요소 외부 클릭시 false
// !로 반대로 나타내면 기준 요소 내부클릭시 false, 기준 요소 외부 클릭시 true 가 됨
console.log('current: ', outsidemenuRef.current);
console.log('!etarget: ', !outsidemenuRef.current.contains(e.target));
document.addEventListener('mousedown', clickOutsideMenu);
return () => {
document.removeEventListener('mousedown', clickOutsideMenu);
};
}, [outsidemenuRef]);
return (
<Modal>
<div className="modal-box" ref={outsidemenuRef}>
<ModalMenu>
<div className="modal-menu-title">
<div>
<a href="/">current community</a>
</div>
</div>
<div className="modal-menu-content">
<div>
<a href="/">Stack Overflow</a>
</div>
<div>
<span>
<a href="/">help</a>
</span>
<span>
<a href="/">chat</a>
</span>
<span>
<Link to="/logout">log out</Link>
</span>
</div>
</div>
<div className="modal-menu-content-2nd">
<a href="/">Meta Stack Overflow</a>
</div>
</ModalMenu>
<ModalMenu>
<div className="modal-menu-title">
<div>
<a href="/">your communities</a>
</div>
<div>
<a href="/">edit</a>
</div>
</div>
<div className="modal-menu-content">
<span>
<a href="/">Stack Overflow</a>
</span>
<span>
<a href="/">1</a>
</span>
</div>
</ModalMenu>
<ModalMenu>
<div className="modal-menu-title">
<div>
<a href="/">more stack exchange communities</a>
</div>
<div>
<a href="/">company blog</a>
</div>
</div>
<div className="modal-menu-box">
<input type="text" placeholder="Find a Stack Exchange community" />
<span className="mini-searchbar">
<BsSearch size={16} />
</span>
</div>
</ModalMenu>
</div>
</Modal>
);
};
export default MenuModal;