dom을 직접 선택해야 하는 경우들이 있다.
1. 엘리먼트의 크기를 가져와야 할 때
2. 스크롤바 위치를 가져와야 할 때
3. 엘리먼트에 포커스를 설정 해줘야 할 때
등등
모달 창 외의 부분을 클릭하게 되면 창이 닫히는 이벤트를 만들어 줄것이다.
(먼저 modal div에 ref를 설정해준 상태이다)
//main.js
const ref = useRef()
useOnClickOutside(ref, () => { setModalOpen(false) })
함수를 하나 만들자.
useOnclickOutside()함수는 ref와 콜백함수를 매개변수로 받고 있다.
import React, { useEffect } from 'react'
export const useOnClickOutside = (ref, handler) => {
useEffect(() => {
const listener = (event) => {
if (!ref.current || ref.current.contains(event.target)) {
return
} else {
handler()
}
}
document.addEventListener("mousedown", listener)
document.addEventListener("touchstart", listener)
return () => {
document.addEventListener("mousedown", listener)
document.addEventListener("touchstart", listener)
};
}, [ref, handler])
}
왜 useEffect를 했을까?
listener의 함수를 살펴보자.
!ref.current : event가 발생했는데 ref가 없을 때
ref.current.contains(event.target): 이벤트의 타겟을 ref가 포함하고 있을 때
(모달 창 안의 내용을 클릭할 때) 이럴 때는 그냥 return을 해준다.
그렇지 않을 경우 handler함수로 이용해 setModatl(false)로 모달 창을 닫아 준다.
[useEffect에서 mount, unMount]
useEffect안에서 마운트가 됐던 컴포넌트의 listner는
return을 통해서 unMount(clear)를 해줘야 한다.
document.addEventListener("mousedown", listener)
document.addEventListener("touchstart", listener)