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

