【问题标题】:Close React Modal关闭反应模式
【发布时间】:2019-04-25 14:22:18
【问题描述】:

我在试图弄清楚如何将功能正常的关闭按钮添加到我的模式时遇到了很多问题 - 构造函数/道具没有工作,我不确定在按钮元素中的 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

【问题讨论】:

标签: reactjs react-dom


【解决方案1】:

这里有几个问题。首先,不要直接操作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 和一些@ 987654338@ 已附上 - 请参阅下面的注释)

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;

【讨论】:

    【解决方案2】:

    看起来您的模态只是基于它是否由父级呈现而打开的。没有一起重新设计这种模式,实现你想要的唯一方法是传递某种 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>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-04
      • 2017-12-28
      • 1970-01-01
      • 1970-01-01
      • 2020-04-18
      • 2021-03-30
      相关资源
      最近更新 更多