Reputation: 505
Making an application (react + redux). It contains a few photos. When you click a photo you get a modal window with bigger photo and comments.
Code for ModalContainer (contains modal window itself):
class ModalContainer extends Component {
state = {
name: '',
comment: '',
}
componentDidMount() {
const { isOpen, closeModal } = this.props
if (isOpen) {
document.body.style.overflow = 'hidden'
}
document.addEventListener('click', closeModal)
}
componentWillUnmount() {
const { closeModal } = this.props
document.body.style.overflow = 'auto'
document.removeEventListener('click', closeModal)
}
inputChange = (e) => {
this.setState({
[e.target.name]: e.target.value,
})
}
putComment = (e) => {
e.preventDefault()
const { comment, name } = this.state
const { photo } = this.props
axios
.post(
`https://boiling-refuge-66454.herokuapp.com/images/${photo.id}/comments`,
{ name: name, comment: comment, date: Date.parse(String(new Date())) }
)
.then((res) => {
console.log(res)
})
this.setState({
name: '',
comment: '',
})
}
render() {
const { name, comment } = this.state
const { closeModal, photo } = this.props
const comments = photo.comments
return (
<>
<Modal
onClick={closeModal}
src={photo.url}
comments={comments}
name={name}
comment={comment}
onChange={this.inputChange}
onSubmit={this.putComment}
/>
</>
)
}
}
export default connect(
({ modal }) => ({
photo: modal.photo,
isOpen: modal.isOpen,
}),
{ closeModal }
)(ModalContainer)
As you can see I have this code document.addEventListener('click', closeModal)
inside componentDidMount()
lifecycle method. Brackets contains action creator closeModal
, which closes my modal. In that case it doesn't work correctly because it launches action creator even if I click inside my modal. So I can't add comment inside.
In this case, what is the proper way to close a modal window by clicking outside a window?
Upvotes: 1
Views: 1828
Reputation: 4352
A common practice is to wrap Modal
in an ModalOverlay
,
style ModalOverlay
to be full screen.
function onOverlayClick(e) {
closeModal()
e.stopPropagation()
}
function onModalClick(e) {
// need to stop propagation to ModalOverlay onClick event
e.stopPropagation()
}
return (
<div className="full-screen" onClick={onOverlayClick}>
<Modal
onClick={onModalClick}
src={photo.url}
comments={comments}
name={name}
comment={comment}
onChange={this.inputChange}
onSubmit={this.putComment}
/>
<div/>
)
Upvotes: 1
Reputation: 2877
if Modal
is a class component you can add ref
to it (if it's a function component use fowardRef
)
<Modal ref={modalNode => (this.modalNode = modalNode)}
and adapt your eventListener
handleClick = e => !this.modalNode.contains(e.target) && closeModal();
componentDidMount() {
const { isOpen, closeModal } = this.props
if (isOpen) {
document.body.style.overflow = 'hidden'
}
document.addEventListener('click', this.handleClick)
}
Upvotes: 2