如何阻止首次访问页面时React子组件重复发起两次API请求
解决React子组件重复发起API请求的问题
问题场景
首页有「全部」「科幻」「喜剧」三个标签,默认选中「全部」标签,调用子组件渲染对应数据时,首次访问页面子组件会重复发起同一个API请求两次。
现有代码
Home组件
import React from 'react'; import ChildComponent from './ChildComponent'; function Home() { return ( <div> <h1>首页组件</h1> <ChildComponent /> </div> ); } export default Home;
ChildComponent组件
import React, { useState, useEffect } from 'react'; function ChildComponent() { const [data, setData] = useState([]); useEffect(() => { fetch('https://api.example.com/data') .then(response => response.json()) .then(data => setData(data)) .catch(error => console.error('Error fetching data:', error)); }, []); return ( <div> <h2>子组件</h2> <ul> {data.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> </div> ); } export default ChildComponent;
解决办法
1. 排查React严格模式
开发环境下,React的Strict Mode会重复执行useEffect、组件构造函数等方法,用来检测代码中的潜在问题,这是正常的开发特性,生产环境不会触发。
- 如果是开发环境的测试场景,不需要修改代码;要是想在开发环境避免这个情况,找到项目根组件(一般是
index.js),去掉<React.StrictMode>的包裹即可。
2. 避免组件重复挂载/渲染
检查首页组件是否被多次挂载,比如路由配置重复、父组件有无必要的状态更新导致重渲染。可以用React.memo包裹子组件,减少不必要的重渲染:
// 在ChildComponent末尾修改 export default React.memo(ChildComponent);
3. 给请求加防重复标记
用useRef标记请求是否已经发起,确保即使组件意外重渲染,也不会重复调用API:
import React, { useState, useEffect, useRef } from 'react'; function ChildComponent() { const [data, setData] = useState([]); // 标记是否已经发起过请求 const hasFetched = useRef(false); useEffect(() => { if (!hasFetched.current) { hasFetched.current = true; fetch('https://api.example.com/data') .then(response => response.json()) .then(resData => setData(resData)) .catch(error => console.error('请求数据出错:', error)); } }, []); return ( <div> <h2>子组件</h2> <ul> {data.map(item => ( <li key={item.id}>{item.name}</li> ))} </ul> </div> ); } export default React.memo(ChildComponent);
内容的提问来源于stack exchange,提问作者MenTalist
相关产品推荐
相关产品推荐

