You need to enable JavaScript to run this app. React中监听POST请求响应的最佳实践是什么?
优惠活动
大模型
产品
解决方案
定价
更多

React中监听POST请求响应的最佳实践是什么?

问题根因

  • 你的commitData没有返回fetch产生的Promise对象,异步操作结果无法被外层捕获,所以handleSubmit里拿到的isSuccess永远是初始的undefined,不会等请求结束再执行后续判断。
  • 之前用await报错是因为你没有给使用await的函数加async声明。
  • 你尝试在事件处理函数内调用hook报错是正常的,hook仅允许在组件顶层、自定义Hook中调用,不需要修改函数名强制在回调内调用hook。

最佳实现方案

不需要把history传入commitData,只需两步调整即可保持逻辑清晰,同时满足需求:

第一步:修改commitData,返回Promise

删除冗余的局部变量,直接返回fetch的执行链,将请求结果通过Promise传递到外层:

export const commitData = (endPoint, data) => {
  return fetch(endPoint, {
    method: 'POST',
    headers: {"Content-Type": "application/json"},
    body: JSON.stringify(data)
  })
  .then(res => {
    if (!res.ok) throw res
    return true // 请求成功返回true
  })
  .catch(err => {
    console.error('提交失败:', err)
    return false // 请求失败返回false
  })
}

第二步:将handleSubmit改为async函数,用await接收请求结果

所有hook(如useHistory、useState返回的history、setError)都在组件顶层声明,仅在回调内使用,完全符合React语法规则:

const handleSubmit = async (e) => {
  e.preventDefault();
  const topic = {id, title, desc, text};
  console.log(topic);
  // 等待异步请求返回后再执行后续逻辑
  const isSuccess = await commitData(topicsEndPoint, topic)
  console.log(isSuccess)
  if (isSuccess) {
    history.push(endPoint)
  } else {
    setError("An error has occured.")
  }
}

可选优化:增加提交中状态避免重复提交

新增一个状态控制提交按钮禁用,防止用户重复点击触发多次请求:

// 组件顶层声明状态
const [submitting, setSubmitting] = useState(false)

const handleSubmit = async (e) => {
  e.preventDefault();
  if (submitting) return // 拦截重复提交
  setSubmitting(true)
  setError('') // 先清空历史错误提示
  const topic = {id, title, desc, text};
  const isSuccess = await commitData(topicsEndPoint, topic)
  setSubmitting(false)
  if (isSuccess) {
    history.push(endPoint)
  } else {
    setError("An error has occured.")
  }
}

// 表单提交按钮添加禁用属性即可
// <button type="submit" disabled={submitting}>提交</button>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.19 09:24:03