ReactJS页面渲染前如何正确发起两个API请求?
React异步请求中状态更新延迟导致的API调用问题解决
问题描述
在React中发起两个异步API请求时,第二个API调用依赖第一个请求返回的player状态,但直接访问useState定义的player变量时,需要等待页面重新渲染才能拿到最新值,导致第二个请求无法正确获取参数。尝试过用isLoading控制加载状态,也试过多种Promise/异步方案(包括用setTimeout实现的非优化Promise),都没解决问题。
原代码实现
状态定义
const [isLoading, setIsLoading] = useState(false);
原API调用代码
useEffect(() => { setIsLoading(true); (async () => { await axios.get(`http://localhost:4242/player/${id}`).then((res) => { const data = res.data; setPlayer({ ...data }); }); await axios .get(`http://localhost:4242/team/${player.team_ID}`) .then((res) => { const data = res.data; setTeam({ ...data }); setIsLoading(false); }); })(); }, []);
渲染代码
<> <Navbar/> {isLoading && <Spinner/>} {player && team && <Player/>} <LoginWidget/> <Footer/> </>
问题原因
React的useState状态更新是异步且批量处理的,在同一个异步函数中调用setPlayer后,立刻访问player变量,拿到的仍然是该函数闭包中的旧值,无法获取刚更新的team_ID,导致第二个API请求参数错误。
修复方案
直接使用第一个API请求返回的响应数据(而非useState的player变量)作为第二个请求的参数,同时改用try-catch处理请求异常,并调整isLoading的设置逻辑,确保无论请求成功或失败都会结束加载状态。
修复后的代码
useEffect(() => { const fetchData = async () => { setIsLoading(true); try { const { data: playerRes } = await axios.get( `http://localhost:4242/player/${id}` ); setPlayer({ ...playerRes }); const { data: teamRes } = await axios.get( `http://localhost:4242/team/${playerRes.team_ID}` ); setTeam({ ...teamRes }); } catch (err) { console.log(err); } setIsLoading(false); }; fetchData(); }, []);
内容的提问来源于stack exchange,提问作者ConnorWitmer
相关产品推荐
相关产品推荐

