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
相关产品推荐
相关产品推荐

