영역 밖 클릭 시 닫기

heyhey·2022년 12월 22일
0

frontend

목록 보기
1/14

지금까지 모달창을 만들기 위해 Mui나 부트스트랩의 도움을 많이 받았었습니다.
제가 직접 만들어 쓰려고 시도를 했었지만, 딱 하나의 문제가 걸려 계속해서 사용했었습니다.
바로 영역 밖을 클릭하였을 때, 꺼지게 하는 기능입니다.
이번 작업에서 셀렉트 박스를 직접 만드는 기회가 생겨 그 기능을 구현해 보았고, 모달창에도 적용시킬 수 있습니다.

방법

셀렉트 박스 전체를 ref 를 이용해 영역을 지정해준 뒤 , 클릭을 하는 곳이 그 영역 안에 있는지 확인을 해주는 방법입니다.

1. 사용하고자 하는 모달창을 만들고, state로 관리합니다.

const [showSelect,setShowSelect] = useState(false)

{showSelect && <SelectBox/>}

2. useRef 를 이용해 ref를 만들어줍니다.

const selectEl = useRef<HTMLDivElement>(null);

<SelcetBox ref={selectEl} />

useRef() 로 바로 사용하게 되면 타입지정이 되지않아 undefined로 인식하여 에러가 나기 때문에 타입을 반드시 지정해줍니다.

3. 클릭 이벤트를 만들어 클릭 이벤트의 요소가 ref 안에 있는지 확인합니다.

const handleClickOutside = (e:MouseEvent)=>{
    if(selectEl.current)
      if(!selectEl.current.contains(e.target as Node))
      {
        setShowSelect(false)
      }
}
  
  
useEffect(()=>{
    if(showSelect){
      window.addEventListener('click',handleClickOutside)
    }
    return()=>{
      window.removeEventListener('click',handleClickOutside)
    }
},[showSelect])

useEffect를 이용해 클릭이벤트를 만들어줍니다.

showSelect가 변할 때마다, 셀렉트창이 열려 있다면 => 클릭할 때마다 함수를 실행시킵니다.

마우스 이벤트를 확인하고, 그 이벤트의 요소가 셀렉트 ref 요소라면 넘어가고, 요소가 아니라면 끄는 함수입니다.

실제로 어떻게 동작하는지 보겠습니다.

우선 selectEl의 current를 확인합니다.


console.log(selectEl.current)

<div  class='select_box'>
  <div class='title'>스펙을 추가해주세요</div>
  <div>
    <span class='cotent'>1</span>
    <span class='cotent'>2</span>
    <span class='cotent'>3</span>
    <span class='cotent'>4</span>
  </div>
</div>
이번에는 셀렉트 박스 안의 아무거나 누르고  클릭 이벤트를 확인합니다. 

console.log(e.target)

<span class='cotent'>3</span>

이제 이게 위의 ref에 포함되어있는지 확인을 하면 원하는 기능이 구현됩니다.
selectEl.current.contains(e.target as Node) => true
(as Node는 e.target의 타입 오류를 막기 위해 추가해줬습니다.)

profile
주경야독

0개의 댓글