useClickOutside
const useEventListener = (eventType, callback, element = window) => {
const refCallback = useRef(callback);
useEffect(() => {
refCallback.current = callback;
}, [callback]);
useEffect(() => {
const handler = (e) => refCallback.current(e);
element.addEventListener(eventType, handler);
return () => element.removeEventListener(eventType, handler);
}, [eventType, element]);
};
const useClickOutside = (ref, cb) => {
useEventListener('click', (e) => {
if (ref.current == null || ref.current.contains(e.target)) return;
cb(e);
});
};
const App = () => {
const [open, setOpen] = useState(false);
const refModal = useRef();
useClickOutside(refModal, () => {
if (open) setOpen(false);
});
return (
<>
<button onClick={() => setOpen(true)}>Open</button>
<div
ref={refModal}
style={{
display: open ? 'block' : 'none',
backgroundColor: 'blue',
color: 'white',
width: 100,
height: 100,
position: 'fixed',
top: 'calc(50% - 50px)',
left: 'calc(50% - 50px)',
}}
>
<span>Modal</span>
</div>
</>
);
};
jsx