如何关闭模态 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)
  }