【问题标题】:React.js + MUI: Modal closes when clicking on Select componentReact.js + MUI:单击选择组件时模式关闭
【发布时间】:2023-01-17 01:22:01
【问题描述】:

出于 MUI 学习目的,我正在创建一个带有模态的简单 CRUD 应用程序。该模式包含一个简单的表单,其中包含一些 TextField 和一个 Select 组件。问题是,当单击“选择”组件时,模式关闭。

模态:

<ClickAwayListener
    onClickAway={handleClickAway}
  >
    <Box sx={{ marginTop: '80px' }}>
      <Button
        sx={{
          borderRadius: '8px',
          backgroundColor: '#fff',
          color: '#091fbb',
          border: '1px solid #091fbb'
        }}
        onClick={handleOpen}
      >
        Add new
      </Button>

      <Modal
        hideBackdrop
        open={open}
        onClose={handleClose}
        sx={{
          position: 'absolute',
          top: '50%',
          left: '50%',
          transform: 'translate(-50%, -50%)',
          backgroundColor: '#fff',
          border: '1px solid #b9c2ff',
          borderRadius: '8px',
          height: 'fit-content',
          width: 400,
          boxShadow: 2,
        }}
      >
        <form
          onSubmit={handleSubmit}
          style={{
            display: 'flex',
            flexDirection: 'column',
            paddingTop: '12px',
            paddingLeft: '18px',
            paddingRight: '18px',
            paddingBottom: '30px',
          }}
        >
          <Typography variant='h6' sx={{ my: 2, textAlign: 'center' }}>ADD NEW PARTICIPANT</Typography>

          <FormControl sx={{ my: 1 }}>
            <Typography variant='body2'>Fullname</Typography>
            <TextField
              variant='standard'
              value={fullname}
              onChange={(e) => setFullname(e.target.value)}
            />
          </FormControl>

          <FormControl sx={{ my: 1 }}>
            <Typography variant='body2'>Gender</Typography>
            <Select
              variant='standard'
              value={gender}
              MenuProps={{
                onClick: e => {
                  e.preventDefault();
                }
              }}
              onChange={(e) => setGender(e.target.value)}
            >
              <MenuItem value="None"><em>None</em></MenuItem>
              <MenuItem value='Male'>Male</MenuItem>
              <MenuItem value='Female'>Female</MenuItem>
              <MenuItem value='Other'>Other</MenuItem>
            </Select>
          </FormControl>

          <FormControl sx={{ my: 1 }}>
            <Typography variant='body2'>Email</Typography>
            <TextField
              variant='standard'
              value={email}
              onChange={(e) => setEmail(e.target.value)}
            />
          </FormControl>

          <FormControl sx={{ my: 1 }}>
            <Typography variant='body2'>Phone nr</Typography>
            <TextField
              variant='standard'
              value={phone}
              onChange={(e) => setPhone(e.target.value)}
            />
          </FormControl>

          <FormControl sx={{ my: 1 }}>
            <Typography variant='body2'>Description</Typography>
            <TextField
              variant='standard'
              value={description}
              onChange={(e) => setDescription(e.target.value)}
              multiline
              rows={3}
            />
          </FormControl>

          { !isLoading && <Button
            variant='contained'
            type='submit'
            sx={{
              backgroundColor: '#091fbb'
            }}>
            Add participant
          </Button>}

          { isLoading && <Button
            variant='contained'
            type='submit'
            disabled
            sx={{
              backgroundColor: '#091fbb'
            }}>
            Adding participant...
          </Button>}

        </form>
      </Modal>
    </Box>
  </ClickAwayListener>

Modal 的处理函数和状态:

const [open, setOpen] = useState(false);
const [fullname, setFullname] = useState('');
const [gender, setGender] = useState('None');
const [email, setEmail] = useState('');
const [phone, setPhone] = useState('');
const [description, setDescription] = useState('');
const [isLoading, setIsLoading] = useState(false);

const handleOpen = () => {
  setOpen(!open);
};

const handleClose = () => {
  setFullname('');
  setGender('None');
  setEmail('');
  setPhone('');
  setDescription('');

  setOpen(false);
};

const handleClickAway = (e) => {
if (!e.target.classList.contains('MuiMenuItem-root')) {
  setFullname('');
  setGender('None');
  setEmail('');
  setPhone('');
  setDescription('');

  setOpen(false);
  }
};

const handleSubmit = (e) => {
  e.preventDefault();
  const newParticipant = { fullname, gender, email, phone, description };

  const requestOptions = {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(newParticipant)
  };

  setIsLoading(true);

  fetch('http://localhost:8000/participants', requestOptions)
  .then(() => {
    setFullname('');
    setGender('None');
    setEmail('');
    setPhone('');
    setDescription('');

    setIsLoading(false);
    setOpen(!open);
  })

};

谁能建议如何解决这个问题?添加 MenuProps 以防止 Select 组件的默认行为和 handleClickAway 函数中的 if 语句对我的情况没有帮助,尽管这帮助了其他面临相同问题的人。

【问题讨论】:

    标签: reactjs material-ui


    【解决方案1】:

    假设目标是让SelectModal中工作而不关闭它,也许Modal的默认行为就足够了,可能没有必要使用ClickAwayListener

    不要直接使用 sx 属性设置 Modal 的样式,而是尝试将模态内容包装在 Box 中并设置此容器的样式。这保留了Modal 的默认行为,因此单击Select 不会触发它的关闭。

    由于Modal 内部检测到点击背景会自行关闭,请考虑使用透明背景设置背景样式而不是禁用它,这样也可以省略 ClickAwayListener 的使用。

    简化示例演示:stackblitz(不包括所有数据处理)

    <Modal
      open={open}
      onClose={handleClose}
      // ? Style the backdrop to be transparent
      slotProps={{ backdrop: { sx: { background: "transparent" } } }}
    >
      <Box
        // ? Style the container Box for modal content
        sx={{
          position: "absolute",
          top: "50%",
          left: "50%",
          transform: "translate(-50%, -50%)",
          backgroundColor: "#fff",
          border: "1px solid #b9c2ff",
          borderRadius: "8px",
          height: "fit-content",
          width: 400,
          boxShadow: 2,
        }}
      >
        {/* Modal content here */}
      </Box>
    </Modal>
    

    【讨论】:

      猜你喜欢
      • 2021-12-06
      • 2019-06-01
      • 2022-06-14
      • 1970-01-01
      • 2019-07-12
      • 2014-04-11
      • 1970-01-01
      • 1970-01-01
      • 2016-09-24
      相关资源
      最近更新 更多