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

React出现Cannot read properties of undefined错误,图片加载失败求助

问题解决:无法获取球员图片并出现Cannot read properties of undefined (reading 'then')错误

错误根源

  1. fetchImages函数未返回Promise:你定义的fetchImages内部执行了Promise.all但没有返回结果,调用fetchImages().then()时,函数返回undefined,而undefined没有.then()方法,直接触发报错。
  2. 渲染逻辑错误:即使图片数据获取成功,当前在每个球员卡片中遍历所有图片,会导致每个卡片显示所有球员的图片,而非对应球员的图片。

修复步骤

1. 修复fetchImages函数

修改函数使其返回Promise,并保留id与图片的关联,方便后续匹配球员:

const fetchImages = async (ids) =>
  Promise.all(ids.map(async (id) => ({ id, image: await fetchImage(id) })));

2. 优化数据关联与渲染

推荐将姓名和图片数据合并,避免渲染时的混乱,以下是两种可行方案:

方案A:合并请求,统一管理球员数据

同时发起姓名和图片请求,合并为包含完整信息的数组,渲染更简洁:

export default function _quarterbacksPage() {
  const [players, setPlayers] = useState([]);

  useEffect(() => {
    const fetchPlayers = async () => {
      try {
        // 同时发起两个请求,提升性能
        const [namesData, imagesData] = await Promise.all([
          fetchFullNames(quarterbacks),
          fetchImages(quarterbacks)
        ]);
        // 根据id合并数据
        const mergedPlayers = namesData.map(nameItem => {
          const imageMatch = imagesData.find(img => img.id === nameItem.id);
          return {
            ...nameItem,
            image: imageMatch ? imageMatch.image : ''
          };
        });
        setPlayers(mergedPlayers);
      } catch (err) {
        console.error(err);
      }
    };

    fetchPlayers();
  }, []);

  return (
    <>
      <_navbar />
      {players.map(({ id, name, image }) => (
        <div className={styles.card} key={id}>
          {image && <img src={image} alt={`${name}的球员照片`} />}
          <Link className={styles.cardText} to={`/quarterback/${id}`}>
            {name}
          </Link>
        </div>
      ))}
    </>
  );
}

方案B:单独维护数据,渲染时匹配id

如果要保留两个独立状态,渲染时通过id找到对应图片:

export default function _quarterbacksPage() {
  const [names, setNames] = useState([]);
  const [images, setImages] = useState([]);

  useEffect(() => {
    fetchFullNames(quarterbacks).then(setNames).catch(console.error);
    fetchImages(quarterbacks).then(setImages).catch(console.error);
  }, []);

  return (
    <>
      <_navbar />
      {names.map(({ id, name }) => {
        const playerImage = images.find(img => img.id === id)?.image;
        return (
          <div className={styles.card} key={id}>
            {playerImage && <img src={playerImage} alt={`${name}的球员照片`} />}
            <Link className={styles.cardText} to={`/quarterback/${id}`}>
              {name}
            </Link>
          </div>
        );
      })}
    </>
  );
}

完整修复后代码示例

结合方案A的完整代码:

import { Link } from "react-router-dom";
import _navbar from "../../NavBar/navbar";
import React, { useEffect, useState } from "react";
import styles from "./card.module.css";

const quarterbacks = [3139477, 4241479, 3918298, 3915511, 2577417];

const fetchFullName = async (id) => {
  const res = await fetch(
    `https://nfl-api-data.p.rapidapi.com/nfl-ath-fullinfo?id=${encodeURIComponent(id)}`,
    {
      headers: {
        "x-rapidapi-key": "secret key",
        "x-rapidapi-host": "nfl-api-data.p.rapidapi.com",
      },
    },
  );
  if (!res.ok) {
    throw new Error(`Name lookup for id '${id}' failed`);
  }
  return (await res.json()).athlete.fullName;
};

const fetchFullNames = async (ids) =>
  Promise.all(ids.map(async (id) => ({ id, name: await fetchFullName(id) })));

const fetchImage = async (id) => {
  const res = await fetch(
    `https://nfl-api-data.p.rapidapi.com/nfl-ath-img?id=${encodeURIComponent(id)}`,
    {
      headers: {
        "x-rapidapi-key": "secret key",
        "x-rapidapi-host": "nfl-api-data.p.rapidapi.com",
      },
    },
  );
  if (!res.ok) {
    throw new Error(`Image lookup for id '${id}' failed`);
  }
  return (await res.json()).image.href;
};

const fetchImages = async (ids) =>
  Promise.all(ids.map(async (id) => ({ id, image: await fetchImage(id) })));

export default function _quarterbacksPage() {
  const [players, setPlayers] = useState([]);

  useEffect(() => {
    const fetchPlayers = async () => {
      try {
        const [namesData, imagesData] = await Promise.all([
          fetchFullNames(quarterbacks),
          fetchImages(quarterbacks)
        ]);
        const mergedPlayers = namesData.map(nameItem => {
          const imageMatch = imagesData.find(img => img.id === nameItem.id);
          return {
            ...nameItem,
            image: imageMatch ? imageMatch.image : ''
          };
        });
        setPlayers(mergedPlayers);
      } catch (err) {
        console.error(err);
      }
    };

    fetchPlayers();
  }, []);

  return (
    <>
      <_navbar />
      {players.map(({ id, name, image }) => (
        <div className={styles.card} key={id}>
          {image && <img src={image} alt={`${name}的球员照片`} />}
          <Link className={styles.cardText} to={`/quarterback/${id}`}>
            {name}
          </Link>
        </div>
      ))}
    </>
  );
}

额外优化建议

  • 使用Promise.all并行发起请求,减少整体等待时间。
  • 可为图片添加默认占位图,处理图片加载失败的情况。
  • 完善alt属性内容,提升页面可访问性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 20:04:53