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

ReactJS async/await调用API时更新的状态无法传递 需提交两次才生效

问题排查与修复方案

核心问题根因

  • React的状态更新函数(setMovieOneInfo、setMovieOneAdjEarnings)属于异步批量更新逻辑,调用更新函数后,当前作用域内的状态变量还是本次渲染开始时捕获的旧值,不会同步更新。
  • 你在pullMovie中调用setMovieOneInfo后直接返回movieOneInfo,返回的永远是更新前的旧状态,第一次执行时传入convertEarnings的就是初始空值/上一次的旧值,第二次执行才能拿到第一次更新后的状态,这就是需要提交两次才生效的核心原因。
  • convertEarnings中同样存在该问题,调用setMovieOneAdjEarnings后直接返回movieOneAdjEarnings,拿到的也是更新前的旧值,打印自然不符合预期。

修复方案

1. 修改pullMovie逻辑

构造完新数据后,先存在临时变量中,用临时变量更新状态的同时返回该临时变量,不要返回旧状态:

const pullMovie = async () => {
  let apiKey = '******'; //已省略有效值,实际可正常使用
  let title1 = movieOne.replaceAll(' ', '+')
  let urlOne = `http://www.omdbapi.com/?t=${title1}&apikey=${apiKey}`

  const response = await fetch(urlOne);
  const data = await response.json();
  // 先构造新数据对象
  const newMovieInfo = {
    title: data.Title,
    year: data.Year,
    poster: data.Poster,
    earnings: data.BoxOffice
  }
  setMovieOneInfo(newMovieInfo)
  // 返回刚生成的新数据,不要返回旧状态
  return newMovieInfo; 
}

2. 修改convertEarnings逻辑

生成格式化后的收益值后,直接返回该新值,不要返回旧状态:

const convertEarnings = async (movie) => {
  let startingAmount = Number(movie.earnings.replace('$', '').replaceAll(',', ''));
  
  let startingYear = Number(movie.year);
  let url= `https://inflation-api.herokuapp.com/api/?value=${startingAmount}&year=${startingYear}`
  
  let response  = await fetch(url);
  let data = await response.json();

  const formatter = new Intl.NumberFormat('en-US', {
    style: 'currency',
    currency: 'USD',
    minimumFractionDigits: 2
  })
  
  const formatAdjEarnings = formatter.format(data.response.adjustedValue)
  setMovieOneAdjEarnings(formatAdjEarnings)
  // 返回刚生成的新值,不要返回旧状态
  return formatAdjEarnings;
}

补充说明

后续如果需要在同一个函数作用域内使用刚更新的状态值,不要依赖状态变量本身,直接使用你传入状态更新函数的参数值即可,状态变量要等到下一次组件重渲染才会更新为新值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 09:09:02