React组件中通过Axios与Hooks调用双API渲染猫数据及图片
在React中结合Hooks和Axios调用双API渲染猫咪数据与图片
我来帮你搞定这个需求!要把猫咪品种数据和对应图片一起渲染,我们可以通过封装API请求、批量获取图片、合并数据这几个步骤来调整现有代码,下面是具体实现方案:
第一步:优化API请求封装
先把API请求逻辑从组件中抽离出来,让代码更清晰易维护,修改你的mainApi.js:
// mainApi.js import axios from 'axios'; export const baseUrl = 'https://api.thecatapi.com/v1/'; // 获取全量猫咪品种列表 export const fetchBreeds = async () => { const response = await axios.get(`${baseUrl}breeds`); return response.data; }; // 根据品种ID获取对应猫咪图片(返回第一张图片的URL) export const fetchCatImageByBreedId = async (breedId) => { const response = await axios.get(`${baseUrl}images/search?breed_id=${breedId}`); return response.data[0]?.url; // 用可选链避免无数据时报错 };
第二步:修改React组件,合并数据与图片
接下来调整CatsList.js,我们会先获取品种列表,再批量请求每个品种的图片,最后把图片URL和品种数据合并后渲染,同时增加加载、错误状态提升用户体验:
// CatsList.js import React, { useState, useEffect } from 'react'; import { fetchBreeds, fetchCatImageByBreedId } from './services/mainApi'; export default function CatsList() { const [breedsWithImages, setBreedsWithImages] = useState([]); const [isLoading, setIsLoading] = useState(true); const [errorMsg, setErrorMsg] = useState(null); useEffect(() => { const loadCatData = async () => { try { setIsLoading(true); // 1. 获取所有猫咪品种数据 const breedList = await fetchBreeds(); // 2. 批量请求每个品种对应的图片,用Promise.all并行处理提升效率 const mergedData = await Promise.all( breedList.map(async (breed) => { const imgUrl = await fetchCatImageByBreedId(breed.id); return { ...breed, imageUrl: imgUrl }; // 合并图片URL到品种对象 }) ); setBreedsWithImages(mergedData); } catch (err) { setErrorMsg('加载猫咪数据失败,请稍后重试'); console.error('请求出错:', err); } finally { setIsLoading(false); // 不管成功失败都结束加载状态 } }; loadCatData(); }, []); // 处理加载/错误状态的UI if (isLoading) return <div className="loading">正在加载可爱猫咪...</div>; if (errorMsg) return <div className="error">{errorMsg}</div>; return ( <ul className="row"> {breedsWithImages.map((cat) => ( <li className="col-md-3 list-item" key={cat.id}> <a href={cat.wikipedia_url} target="_blank" rel="noopener noreferrer" style={{ textDecoration: 'none', color: 'inherit' }} > {/* 渲染猫咪图片,判断URL存在才显示 */} {cat.imageUrl && ( <img src={cat.imageUrl} alt={`${cat.name} 猫咪`} style={{ width: '100%', height: '220px', objectFit: 'cover', borderRadius: '8px', marginBottom: '12px' }} /> )} <h3 style={{ margin: '0 0 8px' }}>{cat.name}</h3> <p style={{ margin: '0 0 8px', fontSize: '14px', color: '#666' }}> 原产地:{cat.origin} </p> <p style={{ fontSize: '13px', lineHeight: '1.5' }}> {cat.description} </p> </a> </li> ))} </ul> ); }
关键细节说明
- 并行请求优化:用
Promise.all同时发起所有图片请求,比逐个串行请求节省大量等待时间 - 错误处理:添加了错误捕获和状态提示,避免页面出现空白或崩溃
- 安全跳转:给外部链接加上
rel="noopener noreferrer",防止潜在的安全风险 - 图片容错:用可选链
?.和条件渲染处理图片请求失败的情况,避免无效图片占位
如果担心品种太多导致请求量过大,还可以考虑添加本地缓存(比如用localStorage存储已请求过的图片URL),或者查看TheCatAPI是否支持批量获取多个品种图片的接口,进一步优化请求次数。
内容的提问来源于stack exchange,提问作者Momin
相关产品推荐
相关产品推荐

