如何关闭模态 window 在 React + Redux 应用程序中单击外部?
How to close a modal window clicking outside in React + Redux app?
制作应用程序(反应+ redux)。它包含几张照片。当你点击一张照片时,你会看到一个模式window,其中有更大的照片和评论。
ModalContainer 代码(包含模态 window 本身):
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)
如您所见,我在 componentDidMount()
生命周期方法中有此代码 document.addEventListener('click', closeModal)
。括号包含动作创建器 closeModal
,它关闭了我的模式。在那种情况下,它无法正常工作,因为即使我在我的模式中单击,它也会启动动作创建器。所以我不能在里面添加评论。
在这种情况下,通过在 window 外部单击来关闭模式 window 的正确方法是什么?
通常的做法是将 Modal
包装在 ModalOverlay
、
中
样式ModalOverlay
为全屏。
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/>
)
如果 Modal
是 class 组件,您可以向其添加 ref
(如果它是功能组件,请使用 fowardRef
)
<Modal ref={modalNode => (this.modalNode = modalNode)}
并调整您的 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)
}
制作应用程序(反应+ redux)。它包含几张照片。当你点击一张照片时,你会看到一个模式window,其中有更大的照片和评论。
ModalContainer 代码(包含模态 window 本身):
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)
如您所见,我在 componentDidMount()
生命周期方法中有此代码 document.addEventListener('click', closeModal)
。括号包含动作创建器 closeModal
,它关闭了我的模式。在那种情况下,它无法正常工作,因为即使我在我的模式中单击,它也会启动动作创建器。所以我不能在里面添加评论。
在这种情况下,通过在 window 外部单击来关闭模式 window 的正确方法是什么?
通常的做法是将 Modal
包装在 ModalOverlay
、
样式ModalOverlay
为全屏。
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/>
)
如果 Modal
是 class 组件,您可以向其添加 ref
(如果它是功能组件,请使用 fowardRef
)
<Modal ref={modalNode => (this.modalNode = modalNode)}
并调整您的 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)
}