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

React应用Promise pending问题:无法加载TheCatAPI图片

React异步获取猫图片数据无法渲染的解决方法

问题描述

调用猫图片API加载图片时,fetchCatImages函数内部打印能得到包含5个对象的数组,但在App组件中调用该函数时,得到的是状态为fulfilled、PromiseResult为数组的Promise对象。尝试了async/await和try-catch两种写法,均无法在组件中正确展示数据。

原代码示例1:

import React from 'react';
import './App.css';

async function fetchCatImages() {
    let images = [];
    await fetch('https://api.thecatapi.com/v1/images/search?limit=5')
        .then((res) => res.json())
        .then((data) => (images = data))
        .catch((e) => {
            console.error('fetch failed!');
            console.error(e);
        });
    console.log('file: App.js ~ line 16 ~ fetchCatImages ~ images', images); 
    // 日志显示包含5个对象的数组

    return images;
}

function App() {
    const images = fetchCatImages();
    console.log('App.js ~ line 7 ~ App ~ images', images);
    // 日志显示Promise {pending}, PromiseState: “fulfilled”, PromiseResult: Array(5) 

    return (
        <>
            {!images.length ? (
                <h3>There are no cats</h3>
            ) : (
                {images.map(({ id, url }) => (
                    <div key={id}>
                        <img src={url} height={50} width={50} />
                    </div>
                ))}
            )}
        </>
    );
}

export default App;

原代码示例2:

function fetchCatImages() {
    let images = [];

    try {
        images = fetch('https://api.thecatapi.com/v1/images/search?limit=5').then((res) => res.json());
    } catch (e) {
        console.error('fetch failed!');
        console.error(e);
    }

    return images;
}

解决方案

React组件渲染是同步过程,不能直接在组件顶层处理异步Promise,必须结合状态管理和useEffect钩子来处理异步数据。

1. 核心修正思路

  • 用useState存储异步获取的图片数据,状态更新触发组件重新渲染
  • 用useEffect在组件挂载时执行异步请求,避免重复调用
  • 优化异步函数写法,避免async/await和.then混用

2. 完整修正代码

import React, { useState, useEffect } from 'react';
import './App.css';

// 优化后的异步请求函数
async function fetchCatImages() {
  try {
    const res = await fetch('https://api.thecatapi.com/v1/images/search?limit=5');
    if (!res.ok) throw new Error(`HTTP错误:${res.status}`);
    const data = await res.json();
    return data;
  } catch (e) {
    console.error('获取猫图片失败:', e);
    return []; // 出错时返回空数组,防止组件渲染报错
  }
}

function App() {
  const [images, setImages] = useState([]);
  const [isLoading, setIsLoading] = useState(true); // 可选:添加加载状态

  useEffect(() => {
    // 定义内部异步函数执行请求
    const loadCatImages = async () => {
      const catData = await fetchCatImages();
      setImages(catData);
      setIsLoading(false);
    };

    loadCatImages();
  }, []); // 空依赖数组:仅在组件首次挂载时执行一次

  // 加载状态展示
  if (isLoading) {
    return <h3>加载猫图片中...</h3>;
  }

  return (
    <>
      {images.length === 0 ? (
        <h3>没有找到猫图片</h3>
      ) : (
        images.map(({ id, url }) => (
          <div key={id} style={{ margin: '5px' }}>
            <img src={url} height={50} width={50} alt={`猫咪图片 ${id}`} />
          </div>
        ))
      )}
    </>
  );
}

export default App;

3. 关键说明

  • 组件顶层不能直接等待Promise:组件渲染是同步的,直接赋值Promise会导致拿到的是未解决的Promise对象,而非实际数据。
  • useEffect的作用:确保异步请求只在组件挂载时执行一次(空依赖数组),避免每次渲染都重复请求。
  • 状态管理:useState保存图片数据,调用setImages更新状态时,React会重新渲染组件并展示最新数据。
  • 错误处理:异步函数中捕获错误并返回空数组,避免组件因数据异常崩溃;添加加载状态提升用户体验。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 22:50:40