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;