use-click-outside
use-click-outside
주어진 요소 또는 요소 그룹 바깥의 클릭 및 터치 이벤트를 감지하는 use-click-outside 훅에 대해 설명해 드릴게요. @mantine/hooks 패키지에서 제공돼요.
출처: 문서
본문
사용법
import { useState } from 'react';
import { Paper, Button } from '@mantine/core';
import { useClickOutside } from '@mantine/hooks';
function Demo() {
const [opened, setOpened] = useState(false);
const ref = useClickOutside(() => setOpened(false));
return (
<>
<Button onClick={() => setOpened(true)}>Open dropdown</Button>
{opened && (
<Paper ref={ref} shadow="sm">
<span>Click outside to close</span>
</Paper>
)}
</>
);
}
API
use-click-outside 훅은 5개의 인자를 받아요:
handler— 외부 클릭 시 호출되는 함수events— 외부 클릭을 유발하는 이벤트 목록(선택), 기본값['mousedown', 'touchstart']nodes— 외부 클릭 이벤트를 유발하지 않아야 하는 노드 목록(선택)enabled— 리스너를 동적으로 활성화/비활성화하는 boolean(선택), 기본값truecapture— capture 단계에서 리스너를 등록할지 여부(선택), 기본값false
훅은 외부 클릭을 캡처할 기준이 되는 요소에 전달해야 하는 ref 객체를 반환해요.
import { useClickOutside } from '@mantine/hooks';
function Example() {
const handleClickOutside = () =>
console.log('Clicked outside of div');
const ref = useClickOutside(handleClickOutside);
return <div ref={ref} />;
}
이벤트 변경하기
기본적으로 use-click-outside는 mousedown과 touchstart 이벤트를 수신해요. 두 번째 인자로 이벤트 배열을 전달해 이 이벤트를 바꿀 수 있어요:
import { useState } from 'react';
import { Paper, Button } from '@mantine/core';
import { useClickOutside } from '@mantine/hooks';
function Demo() {
const [opened, setOpened] = useState(false);
const ref = useClickOutside(() => setOpened(false), ['mouseup', 'touchend']);
return (
<>
<Button onClick={() => setOpened(true)}>Open dropdown</Button>
{opened && (
<Paper ref={ref} shadow="sm">
<span>Click outside to close</span>
</Paper>
)}
</>
);
}
여러 노드
// Will work only with useState, not useRef
import { useState } from 'react';
import { Portal } from '@mantine/core';
import { useClickOutside } from '@mantine/hooks';
function Demo() {
const [dropdown, setDropdown] = useState<HTMLDivElement | null>(
null
);
const [control, setControl] = useState<HTMLDivElement | null>(null);
useClickOutside(() => console.log('outside'), null, [
control,
dropdown,
]);
return (
// We cannot use root element ref as it does not contain dropdown
<div>
<div ref={setControl}>Control</div>
<Portal>
<div ref={setDropdown}>Dropdown</div>
</Portal>
</div>
);
}
Capture 단계
기본적으로 use-click-outside는 bubble 단계에서 이벤트를 수신해요. 요소가 event.stopPropagation()을 호출하면 이벤트가 document에 도달하지 못하고 핸들러가 호출되지 않아요. 다섯 번째 인자로 true를 전달해 대신 capture 단계에서 수신할 수 있어요. 그러면 다른 요소가 이벤트를 막기 전에 핸들러가 호출돼요:
import { useClickOutside } from '@mantine/hooks';
function Demo() {
const ref = useClickOutside(
() => console.log('Clicked outside'),
null,
undefined,
true,
true
);
return <div ref={ref} />;
}
ref 타입 설정
import { useClickOutside } from '@mantine/hooks';
const ref = useClickOutside<HTMLDivElement>(() =>
console.log('Click outside')
);
정의
function useClickOutside<T extends HTMLElement = any>(
handler: (event: MouseEvent | TouchEvent) => void,
events?: string[] | null,
nodes?: (HTMLElement | null)[],
enabled?: boolean,
capture?: boolean
): React.RefObject<T>;
더 알아보기 (Learn more)
- Get started — 시작하기
- use-collapse — use-collapse 훅