Home > Software design >  ReactJS | Pass Render Contents but ADD onClick
ReactJS | Pass Render Contents but ADD onClick

Time:07-15

So I'm trying to get some re-use out of my modals that I need to drop in various spots. What I want to do is to separate the BUTTON that opens the modal from the modal itself. This way, the button could be an icon button, a proper button or some other render-able thing. I could be thinking about this wrong too. I maybe, should pass the modal to the button? Not sure, looking for advise. I'm new to ReactJS, so don't assume I know a thing or two, I've made it through a few tutorials so far :D.

Here is a simple current implementation of the two components tied up together. The problem child I think is the usage of the open State.

import React, { useState } from "react";
import {
  Button,
  Dialog,
  DialogContent,
  DialogTitle,
  DialogContentText,
  DialogActions,
  IconButton,
} from "@mui/material";
import { Edit } from "@mui/icons-material";
import FacilityForm from "./FacilityForm";

function EditFacilityModal(props) {
  const [open, setOpen] = React.useState(false);

  const handleClickOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  const handleSubmit = async (Facility) => {
    let response = await fetch(
      props.FacilitiesURL   "/"   String(Facility.ID),
      {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(Facility),
      }
    );
    if (response.ok) {
    }
    setOpen(false);
  };

  return (
    <div>
      <IconButton
        aria-label="expand row"
        size="small"
        onClick={() => handleClickOpen()}
      >
        <Edit />
      </IconButton>
      <Dialog open={open} onClose={handleClose}>
        <DialogTitle>Edit Facility</DialogTitle>
        <DialogContent>
          <DialogContentText>
            Please provide the following details to edit the existing facility
            in the system.
          </DialogContentText>
          <FacilityForm
            submitActions={handleSubmit}
            title="Edit Facility"
            details="Facility will be saved exactly as shown."
            Facility={props.Facility}
            FacilitiesURL={props.FacilitiesURL}
          />
        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose}>Cancel</Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}

export default EditFacilityModal;

CodePudding user response:

You could outsource your Dialog into a seperate component which takes open and handleClose as props and other content as props i.e dialogContentText and form as a children prop

function App(props) {
  const [openEditFacilityModal, setOpenEditFacilityModal] = React.useState(false);

  const handleClickOpen = () => {
    setOpenEditFacilityModal(true);
  };

  const handleClose = () => {
    setOpenEditFacilityModal(false);
  };

  const handleSubmit = async (Facility) => {
    let response = await fetch(
      props.FacilitiesURL   "/"   String(Facility.ID),
      {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(Facility),
      }
    );
    if (response.ok) {
    }
    setOpenEditFacilityModal(false);
  };

  return <div>
    <IconButton
      aria-label="expand row"
      size="small"
      onClick={() => handleClickOpen()}
    >
      <Edit />
    </IconButton>
    <EditFacilityModal open={openEditFacilityModal} handleClose={handleClose}>
      <FacilityForm
        submitActions={handleSubmit}
        title="Edit Facility"
        details="Facility will be saved exactly as shown."
        Facility={props.Facility}
        FacilitiesURL={props.FacilitiesURL}
      />
    </EditFacilityModal>
  </div>;
  
}


function EditFacilityModal({open, handleClose, dialogContentText, children}) {
  return (
    <div>
      <Dialog open={open} onClose={handleClose}>
        <DialogTitle>Edit Facility</DialogTitle>
        <DialogContent>
          <DialogContentText>
           {dialogContentText}
          </DialogContentText>
          {children}
        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose}>Cancel</Button>
        </DialogActions>
      </Dialog>
    </div>
  );
}

export default EditFacilityModal;

CodePudding user response:

You can separate the button that handles the opening of the modal by handling the open state in a top level component.

Here's an example of your component that control the open state. This way you can outsource the modal component and use it anywhere with any button you want.

// MyComponent.jsx

import { Edit } from "@mui/icons-material";
import { IconButton } from "@mui/material";
import React from "react";
import EditFacilityModal from "./EditFacilityModal";

function MyComponent() {
  const [open, setOpen] = React.useState(false);

  const handleClickOpen = () => {
    setOpen(true);
  };

  const handleClose = () => {
    setOpen(false);
  };

  return (
    <>
      <IconButton
        aria-label="expand row"
        size="small"
        onClick={() => handleClickOpen()}
      >
        <Edit />
      </IconButton>
      <EditFacilityModal
        open={open}
        handleClose={handleClose}
        Facility="Facility"
        FacilitiesURL="FacilitiesURL"
      />
    </>
  );
}

export default MyComponent;
// EditFacilityModal.jsx

import {
  Button,
  Dialog,
  DialogActions,
  DialogContent,
  DialogContentText,
  DialogTitle,
} from "@mui/material";
import FacilityForm from "./FacilityForm";

function EditFacilityModal(props) {
  const handleSubmit = async (Facility) => {
    const response = await fetch(
      props.FacilitiesURL   "/"   String(Facility.ID),
      {
        method: "PUT",
        headers: {
          "Content-Type": "application/json",
        },
        body: JSON.stringify(Facility),
      }
    );
    if (response.ok) {
    }
    props.handleClose();
  };

  return (
    <Dialog open={props.open} onClose={props.handleClose}>
      <DialogTitle>Edit Facility</DialogTitle>
      <DialogContent>
        <DialogContentText>
          Please provide the following details to edit the existing facility in
          the system.
        </DialogContentText>
        <FacilityForm
          submitActions={handleSubmit}
          title="Edit Facility"
          details="Facility will be saved exactly as shown."
          Facility={props.Facility}
          FacilitiesURL={props.FacilitiesURL}
        />
      </DialogContent>
      <DialogActions>
        <Button onClick={props.handleClose}>Cancel</Button>
      </DialogActions>
    </Dialog>
  );
}

export default EditFacilityModal;
  • Related