React中useEffect内async函数致API两次调用的原因及解决需求
API调用两次的原因及解决办法
为什么会调用两次?
- 依赖触发重复执行:你的
useEffect依赖了dataFetched状态。初始dataFetched是false,第一次useEffect执行时,因为!dataFetched为true,会调用fetchData(),紧接着同步执行setDataFetched(true)。状态更新后组件重新渲染,useEffect因为依赖的dataFetched变化,会再次执行。再加上*React严格模式(开发环境默认开启)*会刻意重复调用useEffect来检测潜在bug,这就导致第一次的useEffect被执行两次,进而触发两次API请求。 - 异步逻辑顺序问题:你在调用异步的
fetchData()后立刻同步更新dataFetched,这时候请求还没完成,但状态已经变了,结合严格模式的重复执行机制,就容易出现两次请求。
实现仅调用一次的方法
方法一:移除dataFetched状态,用空依赖数组
这是最简洁的方式,让useEffect只在组件挂载时执行一次,不需要额外状态控制:
React.useEffect(() => { async function fetchData() { // 修正URL缺失的?,否则请求会失败 const response = await fetch( "https://opentdb.com/api.php?amount=5&category=31&difficulty=easy&type=multiple" ); const jsonData = await response.json(); setData(jsonData.results); } fetchData(); }, []); // 空依赖数组,仅组件挂载时执行一次
方法二:保留dataFetched但调整逻辑
如果一定要用dataFetched状态,把setDataFetched(true)放到异步函数内部,确保请求完成后再更新状态,避免同步更新带来的重复触发:
React.useEffect(() => { async function fetchData() { const response = await fetch( "https://opentdb.com/api.php?amount=5&category=31&difficulty=easy&type=multiple" ); const jsonData = await response.json(); setData(jsonData.results); setDataFetched(true); // 请求完成后再标记已获取数据 } if (!dataFetched) { fetchData(); } }, [dataFetched]);
内容的提问来源于stack exchange,提问作者Shin Thant Maung
相关产品推荐
相关产品推荐

