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

React POST请求中使用formData.append()致事件起止时间异常

问题

开发React项目时,创建事件并通过POST请求将事件详情(含JSON对象)和活动海报文件提交到后端,使用formData.append()处理传输。但遇到事件起止时间无法正确保存的问题:调用formData.append()前起止时间设置正确,调用后时间变为当前时间,仅日期保留设置值。

以下是使用的代码:

export default function AddEvent() {
  let navigate = useNavigate();
  const [event, setEvent] = useState({
    eventName: "",
    eventType: "",
    eventLocationType: "",
  });
  const [location, setLocation] = useState("");
  const [startTime, setStartTime] = useState(moment());
  const [endTime, setEndTime] = useState(moment());
  const [selectedImage, setSelectedImage] = useState(undefined);
  const [imageUrl, setImageUrl] = useState(null);

  const { eventName, eventType, eventLocationType } = event;
const onInputChange = (e) => {
    if (e && e.target && e.target.name) {
      setEvent({ ...event, [e.target.name]: e.target.value });
    }
  };

  const handleLocationChange = (event, value) => {
    setLocation(event.target.value);
  };

  const handleStartTimeChange = (event) => {
    if (event && event.target && event.target.name) {
    setStartTime(moment(event.target.value));
      //setStartTime(event.target.value);
    }
  };

  const handleEndTimeChange = (event) => {
    if (event && event.target && event.target.name) {
    setEndTime(moment(event.target.value));
      //setEndTime(event.target.value);
    }
  };

  const onSubmit = async (e) => {
    e.preventDefault();
    console.log({ ...event, location, startTime, endTime, selectedImage });
    const formData = new FormData();
    formData.append("file", selectedImage);
    formData.append(
      "body",
      JSON.stringify({
        ...event,
        location,
        startTime,
        endTime,
      })
    );
    for (let pair of formData.entries()) {
      console.log(pair[0] + ": " + pair[1]);
    }
    
    await axios
      .post("http://localhost:8080/api/event/saveEvent", formData, {
        headers: {
          "Content-Type": "multipart/form-data",
        },
      })
      .then((response) => {
        console.log(response);
        Swal.fire({
          title: "Event saved successfully!",
          icon: "success",
          confirmButtonText: "OK",
        }).then(() => {
          navigate("/");
        });
      })
      .catch((error) => {
        console.log(error);
      });
  };

 return (
    <div style={{ paddingBottom: "30px" }}>
 <FormControl
        encType="multipart/form-data"
        onSubmit={(e) => onSubmit(e)}
        sx={{ display: "flex", width: "50%", paddingLeft: "250px" }}
      >
<FormLabel
              disabled={true}
              sx={{
                paddingBottom: "10px",
                display: "flex",
                justifyContent: "flex-start",
              }}
            >
              Event Start Date & Time
            </FormLabel>
            <LocalizationProvider dateAdapter={AdapterDayjs}>
              <DemoContainer components={["DateTimeField"]}>
                <DateTimeField
                  size="small"
                  label="Start Date & Time"
                  name="startTime"
                  value={startTime}
                  onChange={handleStartTimeChange}
                  sx={{
                    "& .Mui-focus": {
                      "&:focus": {
                        outline: "none",
                        color: "grey",
                      },
                    }
                  }}
                />
              </DemoContainer>
            </LocalizationProvider>
          </div>

          <div>
            <FormLabel
              disabled={true}
              sx={{
                paddingBottom: "10px",
                display: "flex",
                justifyContent: "flex-start",
              }}
            >
              Event End Date & Time
            </FormLabel>
            <LocalizationProvider dateAdapter={AdapterDayjs}>
              <DemoContainer components={["DateTimeField"]}>
                <DateTimeField
                  size="small"
                  label="End Date & Time"
                  name="endTime"
                  value={endTime}
                  onChange={handleEndTimeChange}
                />
              </DemoContainer>
            </LocalizationProvider>
          </div>
        </div>
<Box
          sx={{
            display: "flex",
            flexDirection: "row",
            justifyContent: "flex-end",
          }}
        >
          <Button
            variant="outlined"
            onClick={onCancel}
            style={{ color: "#e6b81a", borderColor: "#e6b81a" }}
          >
            Cancel
          </Button>
          <Button
            variant="contained"
            onClick={onSubmit}
            style={{ backgroundColor: "#e6b81a", marginLeft: "10px" }}
          >
            Save
          </Button>
        </Box>
      </FormControl>
</div>
  );
}
解决方案

问题根源

startTime和endTime存储的是moment对象,而JSON.stringify()无法正确序列化moment对象,会将其转换为包含当前时间的默认格式(仅保留日期部分,时间重置为当前)。

修复步骤

  1. 将moment对象转换为ISO格式字符串
    在序列化到JSON前,把startTime和endTime转换为标准的ISO时间字符串,确保后端能正确解析:

    formData.append(
      "body",
      JSON.stringify({
        ...event,
        location,
        startTime: startTime.toISOString(), // 转换为ISO字符串
        endTime: endTime.toISOString(),     // 转换为ISO字符串
      })
    );
    
  2. 统一日期库(可选但推荐)
    代码中同时使用了moment和dayjs(Material UI的LocalizationProvider用了AdapterDayjs),可能导致兼容性问题。建议统一使用其中一个库:

    • 继续用moment:将Material UI的适配器改为AdapterMoment
    • 改用dayjs:将所有moment()调用替换为dayjs(),并使用dayjs的toISOString()方法
  3. 验证表单提交前的时间值
    可以在onSubmit中先打印转换后的时间,确认格式正确:

    console.log("转换后的开始时间:", startTime.toISOString());
    console.log("转换后的结束时间:", endTime.toISOString());
    

额外优化

  • 避免在useState初始值中直接使用moment(),因为每次组件渲染都会创建新的moment对象,建议用初始ISO字符串或空值:
    const [startTime, setStartTime] = useState(moment().toISOString());
    // 或者如果需要初始为空:
    const [startTime, setStartTime] = useState(null);
    
  • 确保后端能正确解析ISO格式的时间字符串,比如Java后端可以用@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSXXX")注解映射。

内容的提问来源于stack exchange,提问作者Vidushika Dasanayka

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 02:37:55