React使用useEffect+Promise请求API时响应重复打印两次问题
接口响应重复打印2次问题排查与修复
核心原因
- 你使用的是React 18+版本,且项目入口默认开启了React.StrictMode严格模式。该模式在开发环境下会主动执行两次组件挂载、卸载流程,用来提前检测组件副作用的不规范写法:组件首次挂载时useEffect执行一次、触发第一次请求,紧接着组件会被卸载重挂,useEffect再执行一次、触发第二次请求,因此console.log会打印两次接口结果。该行为仅在开发环境存在,生产环境打包后不会重复执行,不影响线上逻辑。
- 代码中存在潜在的重复触发风险:你在
getData函数刚拼接完请求地址就执行setdesireCountry("")修改state,如果后续给useEffect添加了相关依赖,会直接触发effect重跑、多发起一次请求。 - 搜索按钮直接绑定
getData作为点击事件,若存在事件冒泡、误触发场景也会额外发起请求,但这不是你当前遇到两次打印的核心诱因。
修复方案
- 不推荐的快速方案:直接删除入口文件(通常是
src/index.js)中包裹App组件的<React.StrictMode>标签,即可关闭开发环境的双重执行逻辑。但严格模式可以提前帮你发现副作用未清理、生命周期写法不安全等问题,直接关闭会损失开发校验能力。 - 推荐的规范修复方案:给请求加中断清理逻辑,适配严格模式的执行逻辑,同时调整不合理的state更新时机,参考修改如下:
// 调整covidData初始值为空对象,避免首次渲染解构空字符串导致的属性访问异常 const [covidData, setcovidData] = useState({}); const [desireCountry, setdesireCountry] = useState("pakistan"); useEffect(() => { // 初始化请求中断控制器 const abortController = new AbortController(); const getData = async () => { try { const url = `https://covid-19.dataflowkit.com/v1/${desireCountry}`; const covidData = await fetch(url, { signal: abortController.signal // 绑定中断信号 }); const featchedData = await covidData.json(); console.log(featchedData); // 原有对象解构逻辑保持不变 const { Country_text, ["Last Update"]: lastUpdate, ["Total Cases_text"]: totalCases, ["Total Deaths_text"]: deathCases, ["Total Recovered_text"]: recoverCases, ["New Deaths_text"]: newDeaths, ["Active Cases_text"]: activeCases, ["New Cases_text"]: newCases, ["Total Deaths_text"]: totalDeaths, } = featchedData; if (Country_text === "World") { alert("Country name not correct.please Enter a correct country name"); } else { const coronaData = { Country_text, lastUpdate, totalCases, deathCases, recoverCases, newDeaths, activeCases, newCases, totalDeaths, }; setcovidData(coronaData); // 请求成功后再清空输入框,避免请求过程中修改state触发额外重渲染 setdesireCountry(""); } } catch(err) { // 主动中断的请求不弹出错误提示 if (err.name !== 'AbortError') { alert(`server not responding`) } } }; getData(); // 组件卸载/重跑effect前中断未完成的旧请求,避免竞态问题 return () => { abortController.abort(); } }, []);
额外提示:你代码里重复解构了
Total Deaths_text字段,属于冗余代码,可以删掉重复的声明。
内容的提问来源于stack exchange,提问作者arslan_chaudhry
相关产品推荐
相关产品推荐

