프론트엔드/React

리액트 모달 외부 클릭시 창 닫기

카엔입니다 2022. 9. 27. 14:57

해당 코드

const [isToggle, setIsToggle] = useState(false);

const modalRef = useRef<any>();
const closeModalHandler = (e) => {
	if (isToggle && (!modalRef.current || !modalRef.current.contains(e.target))) setIsToggle(false);
};

useEffect(() => {
	window.addEventListener("click", closeModalHandler);
	return () => {
		window.removeEventListener("click", closeModalHandler);
	};
}, []);

return (
	<Modal ref={modalRef}>
		...
	</Modal>
)

모달에 해당하는 DOM을 ref로 지정

클릭 이벤트가 발생하면 모달에 current 상태와 현재 이벤트를 실행한 element가 e.target에 포함되어있는지 확인

useCustomHook

해당 코드를 재사용하기 위해 커스텀 훅으로 만들 수 있다

Custom Hook

import { useEffect, useRef } from 'react'

export default function useOnClickOutsideRef(callback, initialState = null) {
  const thisDomRef = useRef(initialState);

  useEffect(() => {
    function modalCloseHandler(event) {
      if (!thisDomRef.current?.contains(event.target)) {
        callback()
      }
    }
    window.addEventListener('click', modalCloseHandler);

    return () => window.removeEventListener('click', modalCloseHandler);
  }, [callback]);

  return thisDomRef;
}

코드 적용

const App = () => {
    const [isOpen, setIsOpen] = useState(true)
    const modalRef = useOnClickOutsideRef(() => setIsOpen(false))

    return (
	      <div>
	          <button onClick={() => setIsOpen(true)}>Open Modal</button>

            <Modal ref={modalRef} isOpen={isOpen}>
								...
            </Modal>
				</div>
    )
}