如何在 ReactJS 中使用多个对话框和渲染模式

Posted

技术标签:

【中文标题】如何在 ReactJS 中使用多个对话框和渲染模式【英文标题】:How to use multiple dialog boxes and render modals in ReactJS 【发布时间】:2019-08-07 16:46:23 【问题描述】:

我无法弄清楚如何使用 Material UI 的对话框来呈现模态框,在单击按钮时关闭它们,并使其点击不同的东西会显示不同的模态框。

这是我从 Material UI 中获取的对话框组件

import React from 'react';
import Button from '@material-ui/core/Button';
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogContent from '@material-ui/core/DialogContent';
import DialogContentText from '@material-ui/core/DialogContentText';
import DialogTitle from '@material-ui/core/DialogTitle';


class DialogBox extends React.Component 

  render() 
    return (
      <Dialog
      open=this.props.open
      onClose=this.props.handleClose
      aria-labelledby="alert-dialog-title"
      aria-describedby="alert-dialog-description"
    >
      <DialogTitle id="alert-dialog-title">"Use Google's location service?"</DialogTitle>
      <DialogContent>
        <DialogContentText id="alert-dialog-description">
          Let Google help apps determine location. This means sending anonymous location data to
          Google, even when no apps are running.
        </DialogContentText>
      </DialogContent>
      <DialogActions>
        <Button onClick=this.props.handleClose color="primary">
          Okay
        </Button>
      </DialogActions>
    </Dialog>
    );
  



export default DialogBox;

这是我在其中渲染对话框的页面,我在这里将其称为 Modal。如何制作它以便在对话框打开时关闭它,并且我可以单击不同的图片并让它打开一个带有不同文本的对话框?

import React,Component from "react";
import home from "./home.png";
import car from "./car.png";
import bed from "./bed.png";
import pet from "./pet.png";
import Dialog from "./Modal.js";

class Scenarios extends Component 
  constructor()
    super();
    this.state =  open: false ;
  

  openModal = () =>
    this.setState( open: true );
  

  handleClose = () => 
    this.setState( open: false );
  ;

  render() 
    return (
       <section className="App-scenarios">
        <h2> Quick Tips </h2>
        <p>Know What to Do in Different Scenarios during an Earthquake</p>
        <div className="scenario-group">

          <div className="scenario" onClick=this.openModal>
            <img src=car/>
          </div> 

          <div className="scenario" onClick=this.openModal>
          <img src=home/>
            <Dialog open=this.state.open onClose=this.handleClose title="Home" description="text" />
          </div>
          <div className="scenario" >
          <img src=bed/>
          </div>
          

          <div className="scenario">
          <img src=pet/>
          </div>
        </div>
      </section>
    );
    
;

export default Scenarios;

【问题讨论】:

【参考方案1】:

您有一个很好的开始,但您缺少一些项目。您只需要使您的组件更加灵活和可重用(参见下面的 cmets)。

一些注意事项:下面的示例使用ES6 destructuring、ES6 Fat Arrow Functions、map function、spread operator 和callback functions。此外,您不能将可点击元素 (Modal) 包裹在另一个可点击元素 (div) 中。最外层元素 (div) 将仅由 onClick 事件处理程序处理。

工作示例(为简单起见,我没有使用图片,而是使用占位符 example.png 可点击的标题):


组件/模态

import React from "react";
import PropTypes from "prop-types";
import 
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle
 from "@material-ui/core";


// "Modal is a pure function that requires 4 parameters in order to display 
// the "<Modal />" component. This function would be the same as a traditional function:
// 
//   function Modal( deconstructed parameters )  
//     return (
//       <Dialog>
//        ...
//      </Dialog>
//     )
//   

const Modal = ( description, onCloseModal, openModal, title ) => ( 
  <Dialog
    open=openModal
    onClose=onCloseModal
    aria-labelledby="alert-dialog-title"
    aria-describedby="alert-dialog-description"
  >
    <DialogTitle id="alert-dialog-title">title</DialogTitle>
    <DialogContent>
      <DialogContentText id="alert-dialog-description">
        description
      </DialogContentText>
    </DialogContent>
    <DialogActions>
      <Button onClick=onCloseModal color="primary">
        Okay
      </Button>
    </DialogActions>
  </Dialog>
);

// PropTypes throws a warning if any of the 4 required params are
// missing! In addition, it ensures that props are consistent in name
// and declaration from parent component to child component.

Modal.propTypes = 
  description: PropTypes.string.isRequired,
  onCloseModal: PropTypes.func.isRequired,
  openModal: PropTypes.bool.isRequired,
  title: PropTypes.string.isRequired
;

export default Modal;

组件/场景

import React,  PureComponent  from "react";
import PropTypes from "prop-types";


// Scenario will be a PureComponent (stateless, but still a class component) 
// that will open the Modal component with a supplied "description" and 
// "title" via a parent callback function named "handleOpenModal"

class Scenario extends PureComponent 
  openModal = () => 
    const  description, handleOpenModal, title  = this.props;
    handleOpenModal( description, title );
  ;

  render = () => (
    <div className="scenario" onClick=this.openModal>
      <h1>this.props.imgSrc</h1>
    </div>
  );


Scenario.propTypes = 
  description: PropTypes.string.isRequired,
  handleOpenModal: PropTypes.func.isRequired,
  imgSrc: PropTypes.string.isRequired,
  title: PropTypes.string.isRequired
;

export default Scenario;

组件/场景

import React,  Component  from "react";
import Modal from "../Modal";
import Scenario from "../Scenario/";

// A scenarios variable of an array of objects -- makes it so we don't have to 
// repeat <Scenario title=".." description="..."imgSrc=... handleOpenModal=.. /> 
// over and over, instead we map over these objects as "props" and spread
// them out inside of "Scenario" like so: <Scenario ...props />, which 
// would be the same as:  
// <Scenario title=title description=description imgSrc=imgSrc />

const scenarios = [
  
    title: "Car",
    description: "This is a description for a car.",
    imgSrc: "car.png"
  ,
  
    title: "Home",
    description: "This is a description for a home.",
    imgSrc: "home.png"
  ,
  
    title: "Bed",
    description: "This is a description for a bed.",
    imgSrc: "bed.png"
  ,
  
    title: "Pet",
    description: "This is a description for a pet.",
    imgSrc: "pet.png"
  
];

// Scenarios is a stateful class component that'll act as the parent 
// for its "Scenario" children. The children will update the parent via 
// "this.handleOpenModal". Meanwhile, "Modal" will sit inside the parent
// waiting for the parent state updates to affect how its rendered. The 
// Modal will close itself via the parent's "this.handleCloseModal"
// class method when the "Okay" button is clicked.

class Scenarios extends Component 
  state =  description: "", openModal: false, title: "" ;

  handleOpenModal = ( description, title ) => 
    this.setState( description, openModal: true, title );
  ;

  handleCloseModal = () => 
    this.setState( openModal: false );
  ;

  render = () => (
    <section className="App-scenarios">
      <h2> Quick Tips </h2>
      <p>Know What to Do in Different Scenarios during an Earthquake</p>
      <div className="scenario-group">
        scenarios.map(props => (
          <Scenario
            ...props
            key=props.title // this is required for React to know that each "Scenario" that is returned by the "map" function is unique and must be handled as individual components (otherwise React will complain and throw a warning)
            handleOpenModal=this.handleOpenModal
          />
        ))
      </div>
      <Modal ...this.state onCloseModal=this.handleCloseModal />
    </section>
  );


export default Scenarios;

【讨论】:

以上是关于如何在 ReactJS 中使用多个对话框和渲染模式的主要内容,如果未能解决你的问题,请参考以下文章

在同一个 div 中渲染 Reactjs 多个“d3js”子组件

ReactJS:在superagent ajax请求期间显示带有加载消息的模态

reactjs中如何使用map函数和渲染列表

如何在 reactjs 中使用 onclick 事件渲染子组件?

如何在 ReactJS 中触发模型更改的重新渲染?

如何在第一次渲染和点击时都渲染 useQuery? [ReactJS,graphql]