提问人:ConnorWitmer 提问时间:10/29/2023 最后编辑:ConnorWitmer 更新时间:10/29/2023 访问量:39
如何在 reactJS 中呈现我的页面之前正确进行两个 API 调用?
How do I correctly make two API calls prior to rendering my page in reactJS?
问:
尝试异步进行两个 API 调用时,在页面重新呈现之前,我对于第二个 API 调用不会在页面上更新。我正在尝试在使用 .useState()
isLoading
我尝试了几种不同的 promise/异步方法——甚至使用setTimeout()
isLoading
const [isLoading, setIsLoading] = useState(false);
Api Calls
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);
});
})();
}, []);
Render
<>
<Navbar/>
{isLoading && <Spinner/>}
{player && team && <Player/>}
<LoginWidget/>
<Footer/>
</>
编辑:我能够通过使用第一个 API 调用的响应数据而不是尝试访问变量来解决此问题。我还将其切换到 trycatch。useState()
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();
}, []);
答:
1赞
James Hibbard
10/29/2023
#1
如果没有可重现的例子,很难说出为什么会发生这种情况。也许是因为设置为仅在第二个 API 调用完成后,这可能与 React 组件的初始渲染(或重新渲染)不能很好地同步。isLoading
false
无论哪种方式,由于这两个 API 调用不相互依赖,因此最好同时使用它们来触发它们,然后仅在两个调用都完成后才继续。Promise.all
我是这样做的:
useEffect(() => {
setIsLoading(true);
Promise.all([
axios.get(`http://localhost:4242/player/${id}`),
axios.get(`http://localhost:4242/team/${player.team_ID}`)
])
.then(([playerRes, teamRes]) => {
setPlayer({ ...playerRes.data });
setTeam({ ...teamRes.data });
setIsLoading(false);
})
.catch(error => {
// handle errors
});
}, []);
评论
0赞
ConnorWitmer
10/29/2023
谢谢你,我将来将用于我不需要相互协作的 API 调用。不过,为此,我需要从我的播放器 API 调用中访问该值。我能够通过使用第二次调用的响应数据来修复它,我假设我的问题是由于useEffect,我在更新数据之前尝试访问数据。但是,当使用响应中的数据呈现所有内容时,它会按预期工作。谢谢!Promise.all()
team_ID
0赞
James Hibbard
10/29/2023
是的,最初的问题似乎源于在更新之前尝试使用。通过直接使用从第一个 API 调用返回的值,这可确保将正确的 ID 用于第二个 API 调用。很高兴你让它工作:)player.team_ID
0赞
Claudio Puggioni
10/29/2023
#2
由于您使用的是 await,因此还可以尝试以下操作:
使用效果(() => {
(async () => {
setIsLoading(true);
const resp1 = await axios.get(`http://localhost:4242/player/${id}`);
const data1 = resp1.data;
const resp2 = await axios.get(`http://localhost:4242/team/${player.team_ID}`);
const data2 = resp2.data;
if (data1 && data2) {
setPlayer({ ...data1 });
setTeam({ ...data2 });
setIsLoading(false);
}
})();
}, []);
评论