제목이 다소 난잡할 수 있으나, 나의 어휘력으로는 이게 한계였던 것 같다.
Modal 혹은 Overlay, Custom Select를 만들게 되었을 때 종종 그 요소가 아닌 배경을 클릭하거나 다른 Element를 클릭하게 되면 해당 요소를 숨기는 등의 이벤트를 주어야할 경우가 생기게 된다.
단순히 구현만을 생각하면 document에 event를 걸어 해당 요소가 아니라면 callback을 실행하게끔 만들면 되겠지만,
필요한 컴포넌트마다 이러한 이벤트를 작성하기가 번거롭다.
/** 이해를 돕기 위한 예시입니다. */ export const Overlay = props => { // ... const onClickAway = () => ... // 필요한 경우 매번 이렇게 useEffect를 달아주기는 귀찮다. useEffect(() => { document.addEventListener('click', onClickAway); return () => { document.removeEventListener('click', onClickAway); } }, []); return ( <div> // ... </div> ); }
그래서 해당
ref
이외의 요소를 클릭하면 callback
이 실행되는 간단한 훅을 작성할 수 있다.// src/hooks/index.ts import { RefObject, useEffect } from 'react'; export const useClickAway = (target: RefObject<any>, callback: () => void) => { const handleClickAway = (event: any) => { if (target.current && !target.current.contains(event.target)) { callback(); } }; useEffect(() => { document.addEventListener('click', handleClickAway); return () => { document.removeEventListener('click', handleClickAway); }; }, []); };
import { useRef } from 'react'; import { useClickAway } from './src/hooks'; export const Overlay = props => { const ref = useRef(); useClickAway(ref, () => { // ref 이외의 요소를 클릭했을 때 실행되는 액션 }); return ( <div ref={ref}> // ... </div> ); }