import React, {cloneElement, useState} from 'react';
interface ClickOutsideProps {
children: React.FunctionComponentElement<any>;
onClick: (e: Event) => void;
}
const ClickOutside = ({children, onClick}) => {
const [hasGlobalEvent, setHasGlobalEvent] = useState(false);
const handleClick = (reactEvent: React.MouseEvent) => {
if (hasGlobalEvent) return;
const childrenTarget = reactEvent.currentTarget;
const clickOutsideEventHandler = (e: MouseEvent) => {
const outsideClick = !childrenTarget.contains(e.target as Node);
if (onClick && outsideClick) {
onClick(e);
document.removeEventListener('click', clickOutsideEventHandler);
setHasGlobalEvent(false);
}
};
setHasGlobalEvent(true);
document.addEventListener('click', clickOutsideEventHandler);
};
return cloneElement(children, {onClick: handleClick});
};
export default ClickOutside;
import React, {useEffect, useRef, cloneElement} from 'react';
interface ClickOutsideProps {
children: React.FunctionComponentElement<any>;
onClick: (e: Event) => void;
}
const ClickOutside = ({children, onClick}: ClickOutsideProps) => {
const ref = useRef<HTMLElement>();
useEffect(() => {
if (!ref?.current) {
return;
}
const handleClickOutside = e => {
if (onClick && ref.current && !ref.current.contains(e.target)) {
onClick(e);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
return <>{cloneElement(children, {ref})}</>;
};
export default ClickOutside;