UNPKG

rooks

Version:

Essential React custom hooks ⚓ to super charge your components!

57 lines (56 loc) 1.99 kB
import { useEffect, useRef, useCallback } from "react"; import { noop } from "../utils/noop"; /** * useOutsideClick hook * Checks if a click happened outside a Ref. Handy for dropdowns, modals and popups etc. * * @param ref Ref whose outside click needs to be listened to * @param handler Callback to fire on outside click * @param when A boolean which which activates the hook only when it is true. Useful for conditionally enable the outside click * @see https://react-hooks.org/docs/useOutsideClick * @example * ```tsx * import { useOutsideClick } from "./useOutsideClick"; * import { useRef } from "react"; * import { noop } from "../utils/noop"; * * const MyComponent = () => { * const ref = useRef<HTMLDivElement>(null); * const [isOpen, setIsOpen] = useState(false); * const handleOutsideClick = () => setIsOpen(false); * useOutsideClick(ref, handleOutsideClick); * return ( * <div ref={ref}> * <button onClick={() => setIsOpen(true)}>Open</button> * {isOpen && ( * <div>Inside</div> * )} * </div> * ); * } * ``` */ function useOutsideClick(ref, handler, when) { if (when === void 0) { when = true; } var savedHandler = useRef(handler); var memoizedCallback = useCallback(function (event) { if (ref.current && !ref.current.contains(event.target)) { savedHandler.current(event); } }, [ref]); useEffect(function () { savedHandler.current = handler; }); useEffect(function () { if (when) { document.addEventListener("click", memoizedCallback, true); document.addEventListener("ontouchstart", memoizedCallback, true); return function () { document.removeEventListener("click", memoizedCallback, true); document.removeEventListener("ontouchstart", memoizedCallback, true); }; } return noop; }, [ref, handler, when, memoizedCallback]); } export { useOutsideClick };