Last active
April 11, 2019 09:00
-
-
Save erkobridee/fd1d04afc93b9696c55c6b6fce18ecae to your computer and use it in GitHub Desktop.
based on: https://medium.freecodecamp.org/how-to-detect-an-outside-click-with-react-and-hooks-25dbaa30abcd and https://codesandbox.io/s/8484x6zpnj
This file contains hidden or 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 * as React from 'react'; | |
export interface IClickOutsideProps { | |
onClick: () => void; | |
/** element to add the click event listener, default selector is body */ | |
parentTargetQuerySelector?: string; | |
} | |
/** | |
* Function Component to re-use the behavior of click outside | |
* | |
* expects to have a children and a defined onClick callback | |
*/ | |
const ClickOutside: React.FunctionComponent<IClickOutsideProps> = ({ | |
parentTargetQuerySelector = 'body', | |
children, | |
onClick | |
}) => { | |
const refs = React.Children.map(children, () => React.useRef<any>(null)); | |
const appElement = window.document.querySelector(parentTargetQuerySelector) || window.document; | |
const handleClick = React.useCallback( | |
(e: Event) => { | |
const isOutside = refs.every(ref => { | |
if (!ref.current) { | |
return false; | |
} | |
return !ref.current!.contains(e.target); | |
}); | |
if (isOutside) { | |
onClick(); | |
} | |
}, | |
[onClick] | |
); | |
React.useEffect(() => { | |
appElement.addEventListener('click', handleClick); | |
return () => appElement.removeEventListener('click', handleClick); | |
}, [handleClick]); | |
return <>{React.Children.map(children, (element: any, idx) => React.cloneElement(element, { ref: refs[idx] }))}</>; | |
}; | |
export default ClickOutside; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment