React页面加载时fetch重复调用API两次是什么原因?
问题根源
这个接口被调用两次的现象不是代码逻辑bug,是React 18及以上版本开发环境的默认设计,由严格模式(Strict Mode)的重复渲染校验机制触发。
- Create React App新建的项目默认会在入口文件
src/index.js里用<React.StrictMode>包裹整个应用,开启所有严格模式校验规则 - 开发环境下,严格模式会主动执行一次「组件挂载 -> 组件卸载 -> 组件重新挂载」的流程,用来提前排查组件里不规范的副作用写法、过期闭包、内存泄漏等问题
- 你把fetch请求直接写在组件函数的顶层,组件每次渲染、每次重新挂载都会执行这段请求代码,所以页面加载阶段会触发两次接口调用
这个重复执行逻辑只在开发环境生效,生产环境打包部署后,组件只会正常挂载一次,接口也只会调用一次,不会影响线上运行效果。
正确处理方式
不要直接把副作用逻辑(比如接口请求、事件绑定、定时器注册)写在组件函数顶层,应该放到useEffect钩子中管理,配合空依赖数组保证仅在组件挂载时执行,同时写好清理逻辑避免内存泄漏,示例代码如下:
import { useEffect } from 'react'; import logo from './logo.svg'; import './App.css'; function App() { useEffect(() => { // 用AbortController控制请求取消,避免组件卸载后请求仍在执行 const abortController = new AbortController(); fetch('https://localhost:44386/weatherforecast', { signal: abortController.signal }) .then(res => res.text()) .then(data => console.log(data)) .catch(err => { // 忽略主动取消请求抛出的错误 if (err.name !== 'AbortError') console.error(err); }); // 组件卸载时执行清理:取消未完成的请求 return () => abortController.abort(); }, []); // 空依赖数组代表仅在组件首次挂载时执行副作用 return ( <div className="App"> <header className="App-header"> <img src={logo} className="App-logo" alt="logo" /> <p> Edit <code>src/App.js</code> and save to reload. </p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer" > Learn React </a> </header> </div> ); } export default App;
如果不需要严格模式的校验能力,也可以直接到src/index.js中删除根组件外层的<React.StrictMode>标签,关闭后开发环境也不会触发重复挂载,但不推荐这么做——严格模式能提前帮你发现很多潜在的代码隐患,减少线上出问题的概率。
不要为了规避开发环境的两次调用,给请求加全局锁、单例判断这类补丁,这类多余逻辑会被带到生产环境,反而造成不必要的性能开销和逻辑bug。
内容的提问来源于stack exchange,提问作者CraftyFox
相关产品推荐
相关产品推荐

