Home > other >  I want to have a dialog as a separate component in React-MUI
I want to have a dialog as a separate component in React-MUI

Time:12-17

I'm using React and MUI (v5)

I want to show a dialog in my component but I want this dialog as a separate component, like:

function MyComponent() {

    const [ openDialog, setOpenDialog ] = useState(false);

    const handleOpenDialog = () => {
        setOpenDialog(true);
    };

    return (
        <React.Fragment>
            <Button variant="contained" size="medium" onClick={handleOpenDialog}>
                Open Dialog
            </Button>

            <CreateCategory openDialog={openDialog} />

            <Box>
              ...
            </Box>
        </React.Fragment>
    );
}

and the dialog would be like:


export default function CreateCategory(props) {
  const [openDialog, setOpenDialog] = useState(props.openDialog);
  const [newCategoryName, setNewCategoryName] = useState("");

  const handleDialogClose = () => {
    setOpenDialog(false);
  };

  const handleAddCategory = (categoryName) => {
   ...
  };

  const handleCategoryNameChange = (e) => {
    setNewCategoryName(e.target.value);
  };

  return (
    <React.Fragment>
      <Dialog
        fullWidth
        maxWidth={"sm"}
        open={openDialog}
        onClose={handleDialogClose}
      >
        <DialogTitle>Create Video Category</DialogTitle>
        <DialogContent>
          <TextField
            ...
          />
        </DialogContent>
        <DialogActions>
          <Button ...>
            Add Category
          </Button>
          <Button variant="outlined" onClick={handleDialogClose}>
            Close
          </Button>
        </DialogActions>
      </Dialog>
    </React.Fragment>
  );
}

But it is not working, I want to reuse the dialog in another component

I have it in code sandbox https://codesandbox.io/s/quizzical-merkle-ivquu?file=/src/App.js

Rafael

CodePudding user response:

Copying props into state for no reason is an anti-pattern, and it's causing your issue.

You have two states called openDialog (one in the parent and one in the child), and are expecting them to operate as if they're the same.

To correct this, use props.openDialog directly in your component, and pass down the setter function as a prop as well. Then remove the local state version since it won't be used anymore.

// Pass the setter as well
<CreateCategory openDialog={openDialog} setOpenDialog={setOpenDialog} />
const handleDialogClose = () => {
  props.setOpenDialog(false); // Use the prop.
};
<Dialog
  fullWidth
  maxWidth={"sm"}
  open={props.openDialog} // Use value directly here
  onClose={handleDialogClose}
>

In case this is also a source of confusion in the following snippet (which you should remove anyway):

const [openDialog, setOpenDialog] = useState(props.openDialog);

props.openDialog is only used once on the first render to initialize the state. Anytime in the future that the prop changes, the state will not change to match it. It is an initial value.

  • Related