react 외부 영역 클릭시 열린 컴포넌트 닫기

조민혜·2023년 7월 21일
0

React.js

목록 보기
10/12

다양한 컴포넌트를 만들면서 외부 영역 클릭시 닫히는 기능을 자주 쓰게 되는 것 같다.. ( modal, dropdownbox 등등.. )

사용 한 jsx 코드 예시

export const ListMenu = (props) => {
  const horizontalMenuRef = useRef();
  const [clickFlag, setClickFlag] = useState(false);

  // 드랍다운 메뉴 밖 영역 클릭시 닫히게
  useEffect(() => {
    const handleOutsideClose = (e) => {
      if (clickFlag && !horizontalMenuRef.current.contains(e.target)) setClickFlag(false);
    };
    document.addEventListener("click", handleOutsideClose);

    return () => document.removeEventListener("click", handleOutsideClose);
  }, [clickFlag]);

  return (
    <>
      <DropdwonDiv ref={horizontalMenuRef}>
        <MenuDiv onClick={ setClickFlag((prevValue) => !prevValue);} >
        ...
        </MenuDiv>
      </DropdwonDiv>
    </>
  );
};

위처럼 만들어서 사용하다가.. 이미지 처럼 필요할 때마다 컴포넌트 별로 중복된 코드를 계속 쓰게 되길래..
hooks 폴더를 만들고 재사용 가능한 js 파일을 만들어서 사용했다

useOutsideClose.js

import { useEffect } from "react";

const useOutsideClose = (clickFlag, refs, handler) => {
  
  useEffect(() => {
    const handleOutsideClose = (e) => {
      if (clickFlag && !refs.current.contains(e.target)) handler(e);
    };
    
    document.addEventListener("click", handleOutsideClose);
    
    return () => document.removeEventListener("click", handleOutsideClose);
  }, [refs, handler]);
  
};

export default useOutsideClose;

jsx 내부에서는 아래와 같이 사용 하면된다.

// useOutsideClose 불러오기
import useOutsideClose from "../../hooks/handleOutsideClose";
...
// 기존 useEffect 작성을 useOutsideClose로 대체 ( 기존에 사용하던 state 를 넘기기 click state, ref ) 
useOutsideClose(clickFlag, horizontalMenuRef, () => {
  setClickFlag(false);
});

useOutsideClose.js 내용에서 clickFlag 도 넘기지 않고 처리 하고 싶다면,
처리 함수 부분에 let 변수 하나를 두고 제어 해도 좋을 것 같다.

profile
Currently diving deeper into React.js development.

0개의 댓글