다음 이미지와 같이 드랍다운과 모달 외부 영역을 클릭할 때 드랍다운을 닫거나 모달을 닫는 기능을 구현해야 했다.
하지만 해당하는 컴포넌트의 이벤트는 감지하는 법을 알았지만, 해당 컴포넌트 외부 영역에 이벤트를 감지하여 원하는 기능을 구현하는 법은 알지 못했다.
const Modal = ({ closeModal, isOpenModal }: IModalProps) => {
const modalRef = useRef<HTMLDivElement>(null);
useEffect(() => {
const handleClick = (e: MouseEvent) => {
if (modalRef.current && !modalRef.current.contains(e.target as Node)) {
closeModal();
}
};
window.addEventListener('mousedown', handleClick);
return () => window.removeEventListener('mousedown', handleClick);
}, [modalRef]);
return (
<Overlay>
<ModalWrap ref={modalRef}>
<ModalCloseBtn onClick={closeModal} style={{ cursor: 'pointer' }}>
<Image src="/images/close_Btn.png" width={40} height={40} />
</ModalCloseBtn>
</ModalWrap>
</Overlay>
);
};
modal의 열림과 닫힘의 상태는 아래와 같이 useState로 관리했다.
const [isOpenModal, setIsOpenModal] = useState(false)
modal의 외부 영역 클릭 시인데 click이 아니라 mousedown 이벤트인 이유
현재 나의 코드는 modal을 open할 때 click이벤트를 통해서 isOpenModal을 true값으로 바꾼다.
window도 click이벤트를 감지하게 되면 modal을 open하는 이벤트를 listen할 때 이벤트 버블링으로 인해 window 또한 click 이벤트를 listen하게 되어 modal이 열리자마자 닫히기 때문에 click이벤트가 아닌 mousedown이벤트를 사용해야 한다.
!modalRef.current.contains(e.target as Node)
modalRef는 외부 영역과 해당 모달 영역을 구분 짓는 구분 점인 Ref 객체이다.
우리는 이 외부 영역이라는 조건이 있기 때문에 해당 조건을 추가한 것이다.
외부 영역을 클릭 시에는 해당 조건이 true로 나오게 된다.
https://sezzled.tistory.com/147
https://velog.io/@miyoni/TIL37
감사합니다