본문 바로가기

Web Dev/react.js

useOncCickOutside , useClickAway 실전에서 사용하기

반응형

https://usehooks.com/

 

useHooks – The React Hooks Library

A collection of modern, server-safe React hooks – from the ui.dev team

usehooks.com

https://usehooks-ts.com/react-hook/use-on-click-outside

 

useOnClickOutside

Discover how to use useOnClickOutside from usehooks-ts

usehooks-ts.com

useOnClickOutside는 클릭 이벤트가 특정 요소 외부에서 발생했을 때 특정 작업을 수행하는 React 커스텀 훅입니다. 이를 사용하여 모달이나 드롭다운과 같은 요소를 닫을 때 유용하게 활용할 수 있습니다. 아래에 상세한 예시를 제시해드리겠습니다.

먼저, useOnClickOutside 훅을 정의합니다.

import { useEffect } from 'react';

const useOnClickOutside = (ref, handler) => {
  useEffect(() => {
    const listener = (event) => {
      // 클릭된 요소가 ref의 외부에 위치한 경우에만 handler를 호출합니다.
      if (!ref.current || ref.current.contains(event.target)) {
        return;
      }
      handler();
    };

    // 문서 전체에 클릭 이벤트 리스너를 추가합니다.
    document.addEventListener('click', listener);

    // 컴포넌트가 언마운트되거나 ref가 변경될 때 리스너를 제거합니다.
    return () => {
      document.removeEventListener('click', listener);
    };
  }, [ref, handler]);
};

export default useOnClickOutside;

이제 이 훅을 사용하는 예제를 살펴보겠습니다.

import React, { useRef, useState } from 'react';
import useOnClickOutside from './useOnClickOutside';

const App = () => {
  const modalRef = useRef(null);
  const [modalOpen, setModalOpen] = useState(false);

  // 모달 외부 클릭 시 모달을 닫는 핸들러 함수
  const closeModal = () => {
    setModalOpen(false);
  };

  // 모달 토글 핸들러 함수
  const toggleModal = () => {
    setModalOpen(!modalOpen);
  };

  // 모달 바깥을 클릭했을 때의 처리를 위해 훅을 사용합니다.
  useOnClickOutside(modalRef, closeModal);

  return (
    <div>
      <button onClick={toggleModal}>모달 열기</button>
      {modalOpen && (
        <div ref={modalRef} className="modal">
          <p>모달 내용</p>
        </div>
      )}
    </div>
  );
};

export default App;

위 예시에서 useOnClickOutside 훅을 사용하여 모달 외부를 클릭하면 모달이 닫히도록 처리했습니다. modalRef는 모달 요소를 가리키는 useRef 객체이며, 이를 통해 클릭 이벤트가 모달 내부에서 발생한 것인지 외부에서 발생한 것인지를 판단합니다. 클릭된 요소가 모달 내부가 아니라면 closeModal 함수가 호출되어 모달이 닫힙니다.

 

 

useOncCickOutside  해당 hook 을 찾다보니 

 

https://usehooks.com/useclickaway

 

useClickAway React Hook – useHooks

Detect clicks outside of specific component with useClickAway.

usehooks.com

npm i @uidotdev/usehooks
import * as React from "react";
import { useClickAway } from "@uidotdev/usehooks";
import { closeIcon } from "./icons";

export default function App() {
  const [isOpen, setIsOpen] = React.useState(false);
  const ref = useClickAway(() => {
    setIsOpen(false);
  });

  const handleOpenModal = () => {
    if (isOpen === false) {
      setIsOpen(true);
    }
  };

  return (
    <>
      <section>
        <h1>useClickAway</h1>
        <button className="link" onClick={handleOpenModal}>
          Open Modal
        </button>
      </section>
      {isOpen && (
        <dialog ref={ref}>
          <button onClick={() => setIsOpen(false)}>{closeIcon}</button>
          <h2>Modal</h2>
          <p>
            Click outside the modal to close (or use the button) whatever you
            prefer.
          </p>
        </dialog>
      )}
    </>
  );
}

useOncCickOutside 훅과 동일한 작동이 진행된다. 

실제 적용 코드

import React, { useState } from 'react'
import { RepleContentDiv } from '../../Style/RepleCSS'
import { useClickAway } from "@uidotdev/usehooks";
const RepleContent = (props) => {
    const [isOpen, setIsOpen] = React.useState(false);
    const ref = useClickAway(() => {
        setIsOpen(false);
    });

    const handleOpenModal = () => {
        if (isOpen === false) {
            setIsOpen(true);
        }
    };
    // const [ModalFlag, setModalFlag] = useState(false);

    return (
        <div>
            <RepleContentDiv key={props.idx}>
                <div className='author'>
                    <p>{props.repleList.author.displayName}</p>
                    <div className='modalControl'>
                        <span onClick={handleOpenModal}>...</span>
                        {isOpen && (
                            <div className='modalDiv' ref={ref}>
                                <p>수정</p>
                                <p className='delete'>삭제</p>
                            </div>
                        )}

                    </div>
                </div>
                {props.repleList.reple}
            </RepleContentDiv></div>
    )
}

export default RepleContent
반응형