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

React自定义Hook首次渲染返回空数组问题求助

问题解决方法

核心问题分析

  1. Driver组件的useEffect未监听数据更新:你的useEffect依赖项是空数组,仅在组件首次挂载时执行一次,此时useDriversData还未完成数据请求,返回空数组,导致setDriver找不到对应车手。后续Hook拿到完整数据后,useEffect不会重新触发,所以state一直是空的。
  2. 自定义Hook的数据计算未关联状态更新:driverListApiData是每次Hook渲染时重新创建的数组,但没有依赖接口返回的driver状态,导致接口数据更新后,拼接的车手数据不会同步更新。

第一步:修复自定义Hook useDriversData

把拼接数据的逻辑用useMemo包裹,依赖接口返回的状态,确保数据更新时重新计算:

import { useState, useEffect, useMemo } from "react";
import { getDriversStandings } from "../services/reqester";

export const useDriversData = () => {
  const [apiDrivers, setApiDrivers] = useState([]);

  useEffect(() => {
    getDriversStandings().then((result) => {
      setApiDrivers(result.MRData.StandingsTable.StandingsLists);
    });
  }, []);

  // 用useMemo缓存拼接后的车手数据,仅当apiDrivers变化时重新计算
  const driverListApiData = useMemo(() => {
    const list = [];
    // 遍历接口返回的车手数据
    apiDrivers.forEach((driverData) => {
      if (driverData.DriverStandings) {
        driverData.DriverStandings.forEach((data) => {
          const baseData = {
            id: data.Driver.driverId,
            position: data.position,
            points: data.points,
            team: data.Constructors[0].name,
            firstName: data.Driver.givenName,
            lastName: data.Driver.familyName,
          };

          // 根据driverId补充额外数据
          if (data.Driver.driverId === "max_verstappen") {
            list.push({
              ...baseData,
              racingNumber: "https://media.formula1.com/d_default_fallback_image.png/content/dam/fom-website/2018-redesign-assets/drivers/number-logos/MAXVER01.png.transform/2col-retina/image.png",
              nationImg: "https://media.formula1.com/d_default_fallback_image.png/content/dam/fom-website/flags/Netherlands.jpg.transform/2col-retina/image.jpg",
              driverImg: "https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/M/MAXVER01_Max_Verstappen/maxver01.png.transform/2col-retina/image.png",
              driverProfileImg: "https://media.formula1.com/content/dam/fom-website/drivers/2023Drivers/verstappen.jpg.img.1024.medium.jpg/1677069646195.jpg",
              podiums: "80",
              maxPoints: "2080.5",
              grandPrixEntry: "166",
              worldChampionships: "2",
              highestPosition: "1",
              placeBirth: "Hasselt, Belgium",
            });
          } else if (data.Driver.driverId === "perez") {
            list.push({
              ...baseData,
              racingNumber: "https://media.formula1.com/d_default_fallback_image.png/content/dam/fom-website/2018-redesign-assets/drivers/number-logos/SERPER01.png.transform/2col-retina/image.png",
              nationImg: "https://media.formula1.com/d_default_fallback_image.png/content/dam/fom-website/flags/Mexico.jpg.transform/2col-retina/image.jpg",
              driverImg: "https://media.formula1.com/d_driver_fallback_image.png/content/dam/fom-website/drivers/S/SERPER01_Sergio_Perez/serper01.png.transform/2col-retina/image.png",
            });
          }
          // 可继续添加其他车手的判断逻辑
        });
      }
    });
    return list;
  }, [apiDrivers]); // 依赖apiDrivers,数据更新时重新计算

  return driverListApiData;
};

第二步:修复Driver组件

去掉多余的state,直接基于Hook返回的数据进行查找,同时处理加载状态:

import React from "react";
import { useParams } from "react-router-dom";
import { useDriversData } from "../../hooks/useDriversData";

const Driver = () => {
  const driverListApiData = useDriversData();
  const { id } = useParams();

  // 直接查找对应车手
  const driver = driverListApiData.find(data => data.id === id);

  // 数据未加载或未找到车手时显示对应状态
  if (!driverListApiData.length) {
    return <div>加载中...</div>;
  }
  if (!driver) {
    return <div>未找到该车手</div>;
  }

  return (
    <div className="driver-main-container">
      <div className="listing-container">
        <img src={driver.driverProfileImg} alt={`${driver.firstName} ${driver.lastName}`} />
      </div>
      {/* 可添加更多车手详情内容 */}
    </div>
  );
};

export default Driver;

为什么之前的方法无效?

  • 你用await driverListApiData是无效的,因为driverListApiData是React状态,不是Promise,不能用await等待。
  • 重新保存时组件热重载,此时Hook已经拿到了数据,所以渲染正常,但首次挂载时数据还没加载完成,导致state为空。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 19:13:10