关闭 React 模态

Close React Modal

我在尝试弄清楚如何向我的模式中添加一个正常运行的关闭按钮时遇到了很多问题 - constructor/props 一直没有用,我不确定在 onClick= 之后放什么在按钮元素中。

class Modal extends React.Component {

// whenever component gets rendered to the screen we create a new div assigned to this.modalTarget
 componentDidMount() {
  this.modalTarget = document.createElement('div');
  // add class name to modal target
  this.modalTarget.className = 'modal';
  // take the div we just created and append it to the body tag in doc
  document.body.appendChild(this.modalTarget);
  // call method _render
  this._render();
 }

// whenever the component's about to update we do another render
// this render makes sure that if we get a new set of components or children in the modal
// we're going to render those to the parent div as well
 componentWillUpdate() {
  this._render();
 }

// clean up - whenever the component is about to unmount from the screen
// cleans up dom when the modal is removed from the component heirarchy
 componentWillUnmount() {
  // unmounts this.props.children
  ReactDOM.unmountComponentAtNode(this.modalTarget);
  document.body.removeChild(this.modalTarget);
 }

 _render() {
  // take react dom library and render a div that contains this.props.children
  // and render it into this.modalTarget
  ReactDOM.render(
   <Provider store= {store}>
    <Router>
     <div className="modal">
      {this.props.children}
      <button>Close</button>
     </div>
    </Router>
   </Provider>,
   this.modalTarget

您的模态窗口似乎已打开,这仅取决于它是否由父级呈现。除了一起重新构建此模式之外,实现您想要的唯一方法是传递某种 onClose 回调:

class Parent extends React.Component {
  state = { isModalOpen: false };

  render() {
    return (<div>
      // Stuff
      {this.state.isModalOpen &&
        <Modal onClose={() => this.setState({ isModalOpen: false })}/>
      }
      // Stuff
    </div>);
  }
}

在你的Modal中:

<div className="modal">
    {this.props.children}
    <button onClick={this.props.onClose}>Close</button>
</div>

这里有几个问题。首先,远离直接操纵 DOM。 React 使用虚拟 DOM,因此您无需手动添加或删除 DOM 元素。 React 通过 render 方法自动处理这个 DOM 操作。 此外,您需要使用某种 state (isOpen) 来控制此 Modal。它可以通过 React 的本地状态或通过 Redux 的状态。无论哪种方式,都需要对其进行控制和比较。简而言之,如果它是打开的,则渲染 Modal,如果它关闭,则渲染 null.

此外,这个 Modal 组件可以构造为可重用。只需将它作为 child 添加到另一个有状态的 parent 组件,并包含任何 children 您想要在其中呈现的内容。

工作示例:


components/Example.js(父组件)

import React, { Component } from "react";
import Modal from "../Modal";
import "./styles.css";

class Example extends Component {
  state = { isOpen: false };

  handleOpenModal = () => {
    this.setState({ isOpen: true });
  };

  handleCloseModal = () => {
    this.setState({ isOpen: false });
  };

  render = () => (
    <div className="example">
      <h2>Simple Modal Example</h2>
      <button
        className="uk-button uk-button-primary uk-button-small"
        onClick={this.handleOpenModal}
      >
        Open Modal
      </button>
      <Modal isOpen={this.state.isOpen} onCloseModal={this.handleCloseModal}>
        <h1 className="title">Hello!</h1>
        <p className="subtitle">There are two ways to close this modal</p>
        <ul>
          <li>Click outside of this modal in the grey overlay area.</li>
          <li>Click the close button below.</li>
        </ul>
        <button
          className="uk-button uk-button-danger uk-button-small"
          onClick={this.handleCloseModal}
        >
          Close
        </button>
      </Modal>
    </div>
  );
}

export default Example;

components/Modal.js(子组件——它有很多更小的组件,为了可重用性和易于理解而分开——它们基本上很简单divs 附有一些 styles -- 见下面的注释)

import React from "react";
import PropTypes from "prop-types";
import BackgroundOverlay from "../BackgroundOverlay"; // grey background
import ClickHandler from "../ClickHandler"; // handles clicks outside of the modal
import Container from "../Container"; // contains the modal and background
import Content from "../Content"; // renders the "children" placed inside of <Modal>...</Modal>
import ModalContainer from "../ModalContainer"; // places the modal in the center of the page

// this is a ternary operator (shorthand for "if/else" -- if cond ? then : else)
// below can be read like: if isOpen is true, then return/render the modal, else return null
const Modal = ({ children, isOpen, onCloseModal }) =>
  isOpen ? (
    <Container>
      <BackgroundOverlay />
      <ModalContainer>
        <ClickHandler isOpen={isOpen} closeModal={onCloseModal}>
          <Content>{children}</Content>
        </ClickHandler>
      </ModalContainer>
    </Container>
  ) : null;

// these proptype declarations are to ensure that passed down props are 
// consistent and are defined as expected
Modal.propTypes = {
  children: PropTypes.node.isRequired, // children must be a React node
  isOpen: PropTypes.bool.isRequired, // isOpen must be a boolean
  onCloseModal: PropTypes.func.isRequired // onCloseModal must be a function
};

export default Modal;