You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ReactJS中子表单位于模态框内时如何禁用提交按钮

解决方案

你需要把Formik的isSubmitting状态同步到模态框的按钮组件上,以下是具体修改步骤:

1. 修复表单提交逻辑的错误

首先修正CountryForm组件里的提交函数,你原来的代码里拼写错误了catch方法,并且注释了setSubmitting的调用,会导致提交状态无法重置:

// CountryForm 组件的 _onSubmit 方法
function _onSubmit(fields, { setSubmitting }) {
  return fetch(countryService.insertCountry(fields))
    .then(() => {
      setSubmitting(false); // 放开注释,重置提交状态
      handleClose();
      setRecords(countryService.getCountries());
      setNotify({
        isOpen: true,
        message: `Added successfully`,
        type: "success"
      });
    })
    .catch((err) => { // 修正拼写错误 cath → catch
      alert(err);
      setSubmitting(false); // 放开注释,异常场景也重置提交状态
    });
}

2. 改造Popup组件支持自定义操作按钮

因为按钮现在写在Popup组件里,拿不到Form的提交状态,我们给Popup增加自定义按钮的插槽:

// Popup 组件修改
function Popup(props) {
  const classes = useStyles();
  // 新增actions参数接收自定义按钮
  const { title, children, openPopup, setOpenPopup, actions, ...rest } = props;

  return (
    <Dialog
      {...rest}
      open={openPopup}
      maxWidth="sm"
      classes={{ paper: classes.dialogWrapper }}
    >
      <DialogTitle dividers="true" className={classes.dialogTitle}>
        <div style={{ display: "flex" }}>
          <Typography variant="h4" component="div" style={{ flexGrow: 1 }}>
            Country
          </Typography>
        </div>
      </DialogTitle>
      <Divider />
      <DialogContent direction="row">{children}</DialogContent>
      <DialogActions>
        <Grid container className={classes.buttonsContainer}>
          <Box className={classes.buttons}>
            {/* 优先使用传入的自定义按钮,没有就走默认逻辑 */}
            {actions || (
              <>
                <Button
                  className={classes.button}
                  variant="contained"
                  color="primary"
                  type="submit"
                  form="form"
                >
                  Save
                </Button>
                <Button
                  className={classes.button}
                  color="default"
                  fullWidth
                  onClick={() => setOpenPopup(false)}
                >
                  Cancel
                </Button>
              </>
            )}
          </Box>
        </Grid>
      </DialogActions>
    </Dialog>
  );
}

3. 在Countries组件新增按钮状态管理

增加状态存储自定义按钮,传入Popup和CountryForm:

// Countries 组件新增状态
const [popupActions, setPopupActions] = useState(null);

// 渲染组件时传入对应props
return (
  {/* 其他代码不变 */}
  <Popup 
    openPopup={openPopup} 
    setOpenPopup={setOpenPopup}
    actions={popupActions}
  >
    <CountryForm
      handleClose={handleClose}
      setRecords={setRecords}
      setNotify={setNotify}
      setPopupActions={setPopupActions}
    />
  </Popup>
  {/* 其他代码不变 */}
)

4. 在CountryForm里生成带禁用状态的按钮

在Formik的渲染回调里可以直接拿到isSubmitting状态,生成带禁用逻辑的按钮传给上层:

// CountryForm 组件的Formik渲染回调部分
{({ errors, touched, isSubmitting }) => {
  // 生成带禁用状态的按钮,传给Popup
  props.setPopupActions(
    <>
      <Button
        className={classes.button}
        variant="contained"
        color="primary"
        type="submit"
        form="form"
        disabled={isSubmitting} // 提交中禁用按钮
      >
        {isSubmitting ? "提交中..." : "Save"}
      </Button>
      <Button
        className={classes.button}
        color="default"
        fullWidth
        onClick={props.handleClose}
        disabled={isSubmitting} // 提交中禁用取消按钮
      >
        Cancel
      </Button>
    </>
  )
  return (
    {/* 原有Form内容不变 */}
  )
}}

完成以上修改后,表单提交过程中两个按钮都会自动禁用,提交完成或异常后自动恢复可点击状态。

内容的提问来源于stack exchange,提问作者Cleiton Freitas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 06:18:03