Last active
December 10, 2020 20:06
-
-
Save cassler/81221279a49a23b4177af38ef45bb40a to your computer and use it in GitHub Desktop.
useOnClickOutside hook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React, { useRef } from 'react' | |
import useOnClickOutside from './useOnClickOutside' | |
export default function Component() { | |
// Set a ref for the handler to use | |
const ref = useRef(null) | |
// Handler for outside clicks here | |
const handleClickOutside = () => { | |
// Your custom logic here | |
console.log('clicked outside') | |
} | |
// Handler for inside clicks here | |
const handleClickInside = () => { | |
// Your custom logic here | |
console.log('clicked inside') | |
} | |
useOnClickOutside(ref, handleClickOutside) | |
return ( | |
<div | |
ref={ref} | |
onClick={handleClickInside} | |
style={{ width: 200, height: 200, background: 'cyan' }} | |
/> | |
) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { useEffect, RefObject } from 'react' | |
type Event = MouseEvent | TouchEvent | |
// This looks scary becasue of the type definitions | |
function useOnClickOutside<T extends HTMLElement = HTMLElement>( | |
ref: RefObject<T>, | |
handler: (event: Event) => void, | |
) { | |
// Assign the event listener on our ref whenever ref/hanlder are set | |
useEffect(() => { | |
const listener = (event: Event) => { | |
const el = ref?.current | |
// Do nothing if clicking ref's element or descendent elements | |
if (!el || el.contains((event?.target as Node) || null)) { | |
return | |
} | |
handler(event) | |
} | |
document.addEventListener(`mousedown`, listener) | |
document.addEventListener(`touchstart`, listener) | |
return () => { | |
document.removeEventListener(`mousedown`, listener) | |
document.removeEventListener(`touchstart`, listener) | |
} | |
// Reload only if ref or handler changes | |
}, [ref, handler]) | |
} | |
export default useOnClickOutside |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment