Problem: We have a state-controlled modal. When the user clicks anywhere on the document which outside of the modal, the modal should be closed.
To achieve this, we need to create a ref instance to access the desired element by doing this:
const modalRef = useRef<HTMLDivElement>(null);
<div className="modal" ref="modalRef">
<p>Modal Element</p>
</div>
We have access to the DOM element through React's ref instance. Now we will write a function that checks whether the user clicks on the modal (or its children) with the contains function.
const handleClickOutside = (event: MouseEvent) => {
if (ref.current && !ref.current.contains(event.target)) {
setIsModalOpen(false)
}
}
In this code, we are simply asking whether the modal element does contain a clicked point or not. If it does not contain, set the isModalOpen state as false.
When the mouse event is triggered, we can simply call the handleClickOutside function.
useEffect(() => {
document.addEventListener("click", handleClickOutside, true);
return () => {
document.removeEventListener("click", handleClickOutside, true);
};
});