You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

已使用useCallback和useEffect,为何我的React组件仍渲染4次?

React组件渲染时机解析及代码优化

作为React初学者,我尝试使用Axios获取数据,通过useState管理加载、错误、数据状态,结合useEffect和useCallback控制请求逻辑,并添加了console.log("hey")来追踪组件的渲染时机,代码如下:

import { useCallback, useState, useEffect } from "react";
import DriversList from "./components/DriversList";
import axios from "axios";

function App() {
  const [drivers, setDrivers] = useState([]);
  const [isLoading, setIsLoading] = useState(false);
  const [error, setError] = useState(null);

  const apiGetDataHandler = useCallback(() => {
    setIsLoading(true);
    setError(null);

    axios
      .get("http://ergast.com/api/f1/2022/drivers.json?limit=25")
      .then((response) => {
        setIsLoading(false);
        setDrivers(response.data.MRData.DriverTable.Drivers);
      })
      .catch((error) => {
        setError(error.message);
      });
  }, []);

  useEffect(() => {
    apiGetDataHandler();
  }, [apiGetDataHandler]);

  let content = <DriversList drivers={drivers} />;
  console.log("hey");

  if (error) {
    content = <p>{error}</p>;
  }

  if (isLoading) {
    content = <p>Loading...</p>;
  }

  return (
    <>
      <section>{content}</section>
    </>
  );
}

export default App;

渲染次数拆解

你会看到console.log("hey")总共输出3次,对应以下渲染场景:

  • 初始挂载渲染:组件第一次加载时执行,这是首次输出。
  • 加载状态更新渲染:调用apiGetDataHandler后,setIsLoading(true)触发状态变更,组件重新渲染,第二次输出。
  • 请求完成后渲染:
    • 请求成功时,setIsLoading(false)和setDrivers(...)会被React批量处理,触发一次渲染,第三次输出;
    • 请求失败时,setError(error.message)触发渲染,同样是第三次输出(原代码这里遗漏了setIsLoading(false),会导致加载状态一直存在,需要补上)。

代码优化点

  • 修复请求失败的加载状态:在catch块中添加setIsLoading(false),避免请求失败后页面一直显示加载:
.catch((error) => {
  setIsLoading(false);
  setError(error.message);
});
  • useCallback的合理使用:当前apiGetDataHandler的依赖为空数组,确保函数只会在组件初始挂载时创建一次,useEffect也只会执行一次,符合仅触发一次数据请求的需求,这个用法是正确的。

内容的提问来源于stack exchange,提问作者glpsx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 03:24:24