React组件重复发起API请求怎么优化首屏加载?

开发者雨晨 阅读 45

在开发产品列表页时发现,每次刷新页面都会看到两次相同的商品数据请求。我用useEffect在组件里调用axios.get,但好像不管是否依赖项变化都会触发。看浏览器网络请求发现首屏有重复的请求:


function ProductList() {
  useEffect(() => {
    axios.get('/api/products')
      .then(res => setProducts(res.data));
  }, []); // 这里是不是漏了什么?

  return (
    <div>
      {products.map(product => (
        <ProductCard key={product.id} product={product} />
      ))}
    </div>
  );
}

尝试给图片资源用了React.lazy动态导入,但首屏还是有很多重复请求。用Lighthouse检测发现仍有10+多余的JSON请求,应该怎么定位和解决这些重复的API调用呢?

我来解答 赞 5 收藏
二维码
手机扫码查看
1 条解答
芸倩酱~
先说结论:你这个情况大概率是因为组件重复渲染导致的useEffect执行多次。React官方文档里明确说了,依赖项数组为空数组的话,useEffect只会在组件挂载时执行一次。但如果你的组件被卸载再挂载,或者开发环境开了strict mode,那useEffect会执行两次。

先检查你的组件有没有被反复卸载/挂载,比如路由切换或者父组件状态变化导致的。如果是开发环境,React 18之后的strict mode会故意触发两次useEffect,模拟组件卸载再挂载的效果,用来帮你发现副作用问题。

另外你这个代码没有展示setProducts是怎么来的,假设是useState定义的,那问题不大。但要注意有没有可能在useEffect外面被调用,或者在then之前就触发了第二次请求。

可以临时加个console.log('useEffect触发'),看看是不是组件多实例导致的。比如ProductList被用了多次,或者父组件状态更新导致ProductList重复渲染。可以给useEffect里加个isMounted标记,或者用ref来标记是否已经请求过。

优化建议:
确保useEffect只执行一次,用ref控制
如果是SSR,可以考虑next.js的swr或者react-query,做客户端缓存
查看是否有多个ProductList组件同时挂载,可以用React.memo优化
网络面板看请求时间线,确认是不是同时发起的两个请求

举个例子:

const ProductList = () => {
const [products, setProducts] = useState([]);
const isFetched = useRef(false);

useEffect(() => {
if (isFetched.current) return;
isFetched.current = true;

axios.get('/api/products')
.then(res => setProducts(res.data));
}, []);

return (

{products.map(product => (

))}

);
};
点赞 4
2026-02-05 13:07