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

React复用Modal中submit函数无法获取最新text状态的问题

React Modal提交时无法获取最新输入值的解决方案

问题描述

在React中实现了一个可复用的Modal组件,将弹窗的标题、描述、提交函数及弹窗状态存入state。使用text状态收集Modal内的用户评论,输入时text能正常更新,但点击提交按钮时,提交函数无法获取text的最新值,期望提交时能打印出输入的评论内容。

相关代码

主组件

const defaultModal = {
  open: false,
  title: "",
  description: "",
  handleSubmit: null,
};
const Parent = () => {
  const [modal, setModal] = useState(defaultModal);
  const [text, setText] = useState("");

  const handleSubmit = () => {
    console.log(text + " in submit");
    setModal(defaultModal);
  };

  const handleDelete = () => {
    console.log(text + "in delete");
    setModal(defaultModal);
  };

  const openSubmitModal = () => {
    setModal(prev=>({
      ...prev,
      open: true,
      title: "Are you sure to submit",
      description: "now you are submitting",
      handleSubmit: handleSubmit,
    }));
  };

  const openDeleteModal = () => {
    setModal(prev=>({
      ...prev,
      open: true,
      title: "Are you sure to delete",
      description: "now you are deleting",
      handleSubmit: handleDelete,
    }));
  };

  return (
    <Box
      sx={{
        display: "flex",
        flexDirection: "column",
        p: 4,
      }}
    >
      <Box>
        Lorem ipsum dolor sit amet consectetur adipisicing elit. Quo, aliquid?
      </Box>
      <Box>
       {text}
      </Box>
      <Modal
        title={modal?.title}
        description={modal?.description}
        open={modal?.open}
        handleSubmit={modal?.handleSubmit}
        text={text}
        onTextChange={(e) => setText(e.target.value)}
        handleClose={()=>setModal(defaultModal)}
      />
      <Box>
        <ButtonGroup
          variant="contained"
          aria-label="outlined primary button group"
        >
          <Button onClick={openSubmitModal}>submit</Button>
          <Button onClick={openDeleteModal}>delete</Button>
        </ButtonGroup>
      </Box>
    </Box>
  );
};

export default Parent;

Modal组件

export default function Modal({open,title,description,handleSubmit,handleClose,text,onTextChange}) {

  return (
      <Dialog
        open={open}
        onClose={handleClose}
        PaperProps={{
          component: 'form',
          onSubmit: (event) => {
            event.preventDefault();
            handleSubmit();
          },
        }}
      >
        <DialogTitle>{title}</DialogTitle>
        <DialogContent>
          <DialogContentText>
            {description}
          </DialogContentText>
          <TextField
            autoFocus
            required
            margin="dense"
            label="Comments"
            type="text"
            value={text}
            onChange={onTextChange}
            fullWidth
            variant="standard"
          />
        </DialogContent>
        <DialogActions>
          <Button onClick={handleClose}>Cancel</Button>
          <Button type="submit">Submit</Button>
        </DialogActions>
      </Dialog>
  );
}

问题原因

当调用openSubmitModal或openDeleteModal时,会将当前的handleSubmit/handleDelete函数存入modal状态。由于闭包特性,这些函数捕获的是当时的text值(初始为空或之前的旧值)。后续用户输入更新text后,存入modal状态的函数依然引用旧的text值,导致提交时打印的不是最新输入内容。

解决方案

方案1:提交时传递最新的text值

修改Modal组件的表单提交逻辑,将当前的text作为参数传给handleSubmit:

// Modal组件中修改PaperProps的onSubmit
PaperProps={{
  component: 'form',
  onSubmit: (event) => {
    event.preventDefault();
    handleSubmit(text); // 传递最新的text
  },
}}

然后修改父组件的处理函数,接收参数:

const handleSubmit = (currentText) => {
  console.log(currentText + " in submit");
  setModal(defaultModal);
};

const handleDelete = (currentText) => {
  console.log(currentText + " in delete");
  setModal(defaultModal);
};

方案2:不将处理函数存入modal状态,改用类型标识

在modal对象中添加type字段标记操作类型,父组件统一处理提交逻辑:

// 修改defaultModal
const defaultModal = {
  open: false,
  title: "",
  description: "",
  type: "", // 添加type字段,可选值"submit"或"delete"
};

// 修改openSubmitModal和openDeleteModal
const openSubmitModal = () => {
  setModal(prev=>({
    ...prev,
    open: true,
    title: "Are you sure to submit",
    description: "now you are submitting",
    type: "submit",
  }));
};

const openDeleteModal = () => {
  setModal(prev=>({
    ...prev,
    open: true,
    title: "Are you sure to delete",
    description: "now you are deleting",
    type: "delete",
  }));
};

// 新增统一的提交处理函数
const handleModalSubmit = () => {
  if (modal.type === "submit") {
    console.log(text + " in submit");
  } else if (modal.type === "delete") {
    console.log(text + " in delete");
  }
  setModal(defaultModal);
};

// 传递给Modal的handleSubmit改为handleModalSubmit
<Modal
  // ...其他props
  handleSubmit={handleModalSubmit}
  // ...其他props
/>

方案3:使用useRef保存最新的text值

用useRef实时同步text的最新值,处理函数从ref中读取:

const Parent = () => {
  const [modal, setModal] = useState(defaultModal);
  const [text, setText] = useState("");
  const textRef = useRef("");

  // 同步text到ref
  useEffect(() => {
    textRef.current = text;
  }, [text]);

  const handleSubmit = () => {
    console.log(textRef.current + " in submit"); // 从ref读取最新值
    setModal(defaultModal);
  };

  const handleDelete = () => {
    console.log(textRef.current + " in delete");
    setModal(defaultModal);
  };

  // ...其余代码不变
};

以上三种方案都能解决提交时无法获取最新text值的问题,其中方案1和方案2更符合React的状态管理逻辑,推荐优先使用。

内容的提问来源于stack exchange,提问作者somnath navale

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 07:40:02