Danial Asraf Norbee
Danial Asraf Norbee

Reputation: 271

Cannot close Material UI form dialog in React

I have a QR component which has a button for sharing to social media platforms. A form dialog will pop up if I click on the share button. However, I couldn't get the form to close when I clicked on the close button inside the modal. I can see from the background that the share button has a ripple effect as if that's the button being clicked. What did I do wrong? Why is the handleCloseForm function not working even though setShare is set to false.

Here's the code.

import React, { useState, useContext } from "react";
import { makeStyles } from "@material-ui/core/styles";
import Grid from "@material-ui/core/Grid";
import Typography from "@material-ui/core/Typography";
import Button from "@material-ui/core/Button";
import FileCopyIcon from "@material-ui/icons/FileCopy";
import GetAppIcon from "@material-ui/icons/GetApp";
import ShareIcon from "@material-ui/icons/Share";
import QRCode from "qrcode.react";
import { CopyToClipboard } from "react-copy-to-clipboard";
import Snackbar from "@material-ui/core/Snackbar";
import MuiAlert from "@material-ui/lab/Alert";
import { NavLink } from "react-router-dom";
import Tooltip from "@material-ui/core/Tooltip";
import DataApi from "../utils/createContext";
import SocialShare from "./SocialShare";
import Dialog from "@material-ui/core/Dialog";
import DialogActions from "@material-ui/core/DialogActions";
import DialogContent from "@material-ui/core/DialogContent";
import DialogTitle from "@material-ui/core/DialogTitle";

function Alert(props) {
  return <MuiAlert elevation={6} variant="filled" {...props} />;
}

const useStyles = makeStyles((theme) => ({
  margin: {
    margin: theme.spacing(1),
  },
  gridContainer: {
    paddingLeft: "20px",
    paddingRight: "20px",
    paddingTop: "20px",
  },
}));

export default function QRGenerator() {
  const classes = useStyles();

  const [qrcode, setQrcode] = useState({
    value: "",
    copied: false,
  });

  const [share, setShare] = useState(false);

  const handleFormDialog = () => {
    setShare(true);
  };

  const handleCloseForm = () => {
    setShare(false);
  };

  const downloadQR = () => {
    const canvas = document.getElementById("qrc");
    const pngUrl = canvas
      .toDataURL("image/png")
      .replace("image/png", "image/octet-stream");
    let downloadLink = document.createElement("a");
    downloadLink.href = pngUrl;
    downloadLink.download = "QR_" + adminId + ".png";
    document.body.appendChild(downloadLink);
    downloadLink.click();
    document.body.removeChild(downloadLink);
  };

  //const hostname = window.location.hostname;

  const [open, setOpen] = useState(false);

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

  const handleClose = (event, reason) => {
    if (reason === "clickaway") {
      return;
    }
    setOpen(false);
  };

  const { userData } = useContext(DataApi);

  const adminId = userData.adminId;

  return (
    <div>
      <div style={{ textAlign: "center" }}>
        <Grid container className={classes.gridContainer}>
          <Grid item xs={12}>
            <Tooltip title="Open new tab to URL Form" arrow>
              <NavLink
                to={`/checkin/${adminId}`}
                style={{ color: "inherit", textDecoration: "inherit" }}
                target="_blank"
              >
                <QRCode
                  id="qrc"
                  // value={`http://${hostname}/checkin/${adminId}`}
                  value={`http://localhost:3000/checkin/${adminId}`}
                  size={300}
                  bgColor={"#fff"}
                  fgColor={"#45046a"}
                  level={"H"}
                  includeMargin={false}
                />
              </NavLink>
            </Tooltip>
          </Grid>

          <Grid item xs={12}>
            <Tooltip title="Download QR code" arrow>
              <Button
                variant="contained"
                color="primary"
                size="medium"
                style={{ width: "250px" }}
                className={classes.margin}
                onClick={downloadQR}
              >
                <GetAppIcon /> Download
              </Button>
            </Tooltip>
          </Grid>

          <Grid item xs={12}>
            <Tooltip title="Share" arrow>
              <Button
                variant="contained"
                color="primary"
                size="medium"
                style={{ width: "250px" }}
                className={classes.margin}
                onClick={handleFormDialog}
              >
                <ShareIcon /> Share
                <Dialog
                  open={share}
                  onClose={handleCloseForm}
                  aria-labelledby="form-dialog-title"
                >
                  <DialogTitle id="form-dialog-title">Share</DialogTitle>
                  <DialogContent>
                    <SocialShare adminId={adminId} />
                  </DialogContent>
                  <DialogActions>
                    <Button onClick={handleCloseForm} color="primary">
                      Close
                    </Button>
                  </DialogActions>
                </Dialog>
              </Button>
            </Tooltip>
          </Grid>
        </Grid>

        <Typography
          align="center"
          variant="caption"
          paragraph="true"
          className={classes.margin}
        >
          <Tooltip title="Copy to clipboard" arrow>
            <CopyToClipboard
              text={`http://localhost:3000/checkin/${adminId}`}
              onCopy={() => setQrcode({ ...qrcode, copied: true })}
            >
              <Button
                variant="contained"
                color="primary"
                size="medium"
                style={{ width: "250px" }}
                className={classes.margin}
                onClick={handleClick}
              >
                <FileCopyIcon /> Copy to Clipboard
              </Button>
            </CopyToClipboard>
          </Tooltip>

          {/* {qrcode.copied ? <span style={{ color: "red" }}> Copied.</span> : null} */}
          {qrcode.copied ? (
            <Snackbar open={open} autoHideDuration={2000} onClose={handleClose}>
              <Alert onClose={handleClose} severity="success">
                Form URL Copied to Clipboard!
              </Alert>
            </Snackbar>
          ) : null}
        </Typography>
      </div>
    </div>
  );
}

Upvotes: 1

Views: 3216

Answers (1)

hangindev.com
hangindev.com

Reputation: 4883

You should not put the Dialog inside Button. If you try to console.log inside handleFormDialog and handleCloseForm, you will see when you click the close button, it will trigger handleCloseForm and handleFormDialog consecutively so the share state remains true.

Try to put it outside Tooltip:

<Tooltip title="Share" arrow>
  <Button
    variant="contained"
    color="primary"
    size="medium"
    style={{ width: "250px" }}
    className={classes.margin}
    onClick={handleFormDialog}
  >
    <ShareIcon /> Share
  </Button>
</Tooltip>
<Dialog
  open={share}
  onClose={handleCloseForm}
  aria-labelledby="form-dialog-title"
>
  <DialogTitle id="form-dialog-title">Share</DialogTitle>
  <DialogContent>
    <SocialShare adminId={adminId} />
  </DialogContent>
  <DialogActions>
    <Button onClick={handleCloseForm} color="primary">
      Close
    </Button>
  </DialogActions>
</Dialog>

Upvotes: 4

Related Questions