useOnClickOutside.tsx 1.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041
  1. import {useEffect} from 'react';
  2. // hook from https://usehooks.com/useOnClickOutside/
  3. function useOnClickOutside<T extends HTMLElement = HTMLElement>(
  4. ref: React.RefObject<T> | T | null,
  5. handler: (event: MouseEvent | TouchEvent) => void
  6. ) {
  7. useEffect(
  8. () => {
  9. const listener = (event: MouseEvent | TouchEvent) => {
  10. if (!ref) {
  11. return;
  12. }
  13. let el: T | null;
  14. if ('current' in ref) {
  15. el = ref.current;
  16. } else {
  17. el = ref;
  18. }
  19. // Do nothing if clicking ref's element or descendent elements
  20. if (!el || el.contains(event.target as Node)) {
  21. return;
  22. }
  23. handler(event);
  24. };
  25. document.addEventListener('mousedown', listener);
  26. document.addEventListener('touchstart', listener);
  27. return () => {
  28. document.removeEventListener('mousedown', listener);
  29. document.removeEventListener('touchstart', listener);
  30. };
  31. },
  32. // Reload only if ref or handler changes
  33. [ref, handler]
  34. );
  35. }
  36. export default useOnClickOutside;