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

React添加async/await后API仍需点击两次才触发的问题

问题核心原因

点击两次才调用成功的本质是请求参数读取时序错误,你的代码存在3个明确问题:

  • 混用async/await和.then()链式写法,GetSeatPrices()调用前没有加await,第一次点击时localStorage刚写入就立刻发起请求,请求函数内部大概率还没读到刚写入的参数,就用旧值/空值发了请求,自然返回异常;第二次点击时localStorage已经存了上一次点击写入的正确参数,所以才能请求成功
  • 写在点击回调内部的mounted、pricemounted变量完全无效,每次点击触发函数执行时,这两个变量都会被重新初始化为true,根本起不到组件卸载后阻止状态更新的作用
  • 两个接口没有统一的错误捕获,一旦其中一个接口请求失败你拿不到任何报错提示,很难定位问题
修复后代码

把异步写法统一,调整请求执行时序,修正挂载状态标记的位置:

const [seatData, setSeateData] = React.useState([]);
const [seatPrice, setSeatPrices] = React.useState([]);
// 组件挂载状态用ref存,放在组件作用域顶层
const isMounted = React.useRef(true);

// 组件卸载时修改标记,防止内存泄漏
React.useEffect(() => {
  return () => {
    isMounted.current = false;
  }
}, [])

const showTimeHandleClicked = async (bookData, showDate) => {
  // 先同步完成所有本地存储写入,再发请求
  localStorage.setItem("venue", "539")
  localStorage.setItem("movieDate", showDate.date)
  localStorage.setItem("showtime", bookData.showtimeId)
  localStorage.setItem("MovieShowtime", bookData.showtime)

  try {
    // 两个接口没有依赖关系,直接用Promise.all并行请求,减少等待时间
    const [seatResponse, priceResponse] = await Promise.all([
      GetSeatArrangement(),
      GetSeatPrices()
    ])
    
    // 组件未卸载时再更新状态
    if (isMounted.current) {
      setSeateData(seatResponse?.data?.reservedSeats)
      setSeatPrices(priceResponse?.data?.ticketPrices)
    }
  } catch (error) {
    console.error('场次座位信息请求失败:', error)
  }
}

补充排查点:如果改完还是有问题,直接去看GetSeatArrangement和GetSeatPrices的内部实现,确认这两个函数是不是同步读取localStorage参数,如果这两个函数内部也有异步读取参数的逻辑,需要把参数直接通过入参传给两个请求函数,不要依赖localStorage做参数传递,从根源上避免时序问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.31 11:27:15