I have implemented a Modal and ModalManager component, aiming to ensure that the modal only closes when clicking outside of it or on the close button. However, I’ve encountered an issue where the modal sometimes closes when clicking inside the modal itself, despite this not being the desired behavior.
While some modals function as expected, others exhibit this unintended behavior. I can pinpoint the issue, but I’m looking for insights or potential causes related to the code that might be affecting the behavior.
Modal.jsx
import React, { useRef, useEffect } from 'react';
import PropTypes from 'prop-types';
import ModalCSS from 'modals/Modal.module.scss';
function Modal({ closeModal, content }) {
const modalRef = useRef(null);
console.log('[Modal.jsx] Modal component mounted');
useEffect(() => {
const handleOutsideClick = (event) => {
if (modalRef.current && !modalRef.current.contains(event.target)) {
console.log('[Modal.jsx] Clicked outside modal, closing modal');
closeModal();
}
};
document.addEventListener('mousedown', handleOutsideClick);
return () => {
console.log('[Modal.jsx] Modal component unmounted');
document.removeEventListener('mousedown', handleOutsideClick);
};
}, [closeModal]);
const handleModalClick = (event) => {
console.log('[Modal.jsx] Clicked inside modal, preventing propagation');
// prevent the click from propagating to the parent div
event.stopPropagation();
};
return (
<div className={ModalCSS.ModalContainer}>
<div
ref={modalRef}
className={ModalCSS.ModalContent}
onClick={handleModalClick}
>
{React.cloneElement(content, { onClose: closeModal })}
</div>
</div>
);
}
Modal.propTypes = {
closeModal: PropTypes.func.isRequired,
content: PropTypes.node.isRequired,
};
export default Modal;
import React, { useEffect, memo } from 'react';
import PropTypes from 'prop-types';
import Modal from 'modals/Modal';
// * ModalManager component: manages the rendering of the modal
const ModalManager = memo(({ content, closeModal }) => {
useEffect(() => {
console.log('[ModalManager] rendered');
console.log('[ModalManager] Content:', content);
console.log('[ModalManager] closeModal function:', closeModal);
}, [content, closeModal]);
if (!content) {
console.log('[ModalManager] No content to display, rendering null');
return null; // if there's no content, don't render anything
}
return <Modal closeModal={closeModal} content={content} />;
});
ModalManager.displayName = 'ModalManager';
ModalManager.propTypes = {
content: PropTypes.node, // content can be any renderable React node
closeModal: PropTypes.func.isRequired,
};
export default ModalManager;
What I Tried:
Implemented onClick handlers on the modal to prevent propagation when clicking inside.
Added event listeners for clicks outside the modal to close it.
Used React.cloneElement to pass the onClose handler to the modal content.
Expected Behavior:
The modal should only close when clicking outside of the modal or on the close button (faX).
Clicking inside the modal content should not trigger the closing behavior.
siid_14 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.