在我的小react项目中,我需要在后续的api调用中使用一个API调用的id。我可以访问第一次调用的数据,但不知道如何在第二次调用中使用它。我尝试使用字符串文字来访问所有的id,这样URL就可以直接从其他API中选择每个id,但它只是返回随机的ID。
下面是我的代码
import React, { Component } from "react";
import axios from "axios";
export default class Cat extends Component {
state = {
imagedata: [],
data: [],
CatWeight: "",
CatMetric: "",
}
componentDidMount(){
this.fetchCountryData();
this.fetchImageUrl();
}
fetchCountryData = async () => {
const url = "https://api.thecatapi.com/v1/breeds";
try {
const response = await axios.get(url);
const data = await response.data;
console.log(data)
this.setState({
data,
});
} catch (error) {
console.log(error);
}
};
fetchImageUrl = async () =>{
// This is the Place I'm having issue with. The line below. where imgurl becomes https://api.thecatapi.com/v1/images/search?breed_id=char as an example
// The id is coming from the First API id's
const imgurl = `https://api.thecatapi.com/v1/images/search?breed_id=${this.state.data.map((item) => { return item.id })} `
try {
const response = await axios.get(imgurl);
const imagedata = await response.data;
console.log(imagedata)
this.setState({
imagedata,
});
} catch (error) {
console.log(error);
}
};
render() {
return (
<div>
{
this.state.imagedata.map((item, id) =>{
return <ul key={id}>{item.id}</ul>
})
}
</div>
)
}
}
2条答案
按热度按时间k10s72fa1#
我不知 prop 体的API,但看起来那个端点只需要一个id。通过使用map,你给它一个id数组。您可能需要为每个ID进行单独的API调用。
nle07wnf2#
(注:根据评论意见对答案进行了重大更新。)
你的原稿有一处排印错误。我不知道这是否只是在StackOverflow中,或者它是否也在代码中失败。但搜索网址看起来像
是
breed_ids
,复数,不是breed_id
。此外,它只需要一个单一的品种ID,而不是它们的列表,所以你需要为每个单独的调用。在大多数情况下(64/67),图像URL已经在响应中,没有理由再次获取它。因此,我们可以只获取少数缺失的元素,并使用
Promise.all
合并它们来处理输出。这里有一个技术,它不试图使用你的React设置,而是一个简单的innerHTML
在一些文本操作之上,并使用原生的fetch
而不是axios
:因为
Promise.all
在其输入数组中接受标量值和Promises,所以我们不必在Promise
中 Package 原始文档中的那些值。而不是我们可以直接写
而且它的性能会稍微好一点。但我还是更喜欢写出来的版本,只是出于对一致性的渴望。
另外,如果您在支持optional chaining operator的环境中工作(大多数但不是所有的通用环境),那么
最好写成
更新--分解
一个评论要求代码分解。下面是一个尝试:
我们首先获取数据并将结果转换为对象。我使用了内置的
fetch
调用,而不是导入axios,但是我们可以用axios做一些非常类似的事情。请注意,我们在这里使用的是直接的promise,而不是
async-await
。这当然可以用aysnc-await
风格重写,但是,特别是当我使用Promise.all
时,我看不到太多优点。我们从调用中得到的结果是一个数组。我们在该数组上使用
Array.prototype.map
,将一个品种数组转换为另一个数组,如下一节所示:在这里,我们测试对象是否已经具有我们想要的URL属性。如果是这样,我们返回一个已经解析的Promise,该Promise的对象具有在数组中的breed对象中找到的
name
和url
属性。如果没有(在我的测试中只有几个),我们为该品种构建图像搜索url,调用fetch
,当结果promise解析时,我们将此响应转换为resp .json ()
对象,最后从这个对象构建name
/url
对象。在条件语句的任一分支中,我们返回一个Promise。这是一个Promises数组。
我们使用Promise.all将
name
/url
对象的Promise数组转换为name
/url
对象数组的Promise。这个Promise将在我们提供的所有Promises都已解析时解析,它将返回一个包含调用结果的数组。例如,如果我们有这个:它将解析(在3秒内,当最终的promise解析时)为数组
['foo', 'bar', 'baz']
。如果我们加上这个:则它将以值
'qux'
拒绝(在两秒内,当第一个承诺被拒绝时)。Promise.all
是一个真实的的方便。我们现在有一个承诺,当一切成功时,给我们一系列的品种。这只是创建一个HTML字符串并将其插入到文档中。你需要查阅你的React文档来找到与React等效的异步处理。但应该不难。
最后,如果有一个错误,其中一个Promises无法解决,拒绝原因将出现在这里。你可能也会用React技术来处理这个问题。