使用 axios 从 Dog API 获取数据并将数据保存到新数组中
fetching data from the Dog API using axios and saving data into a new array
我目前正在使用 Typescript 使用 NextJS 应用程序,我的问题出在功能方面:我正在使用 Dog API 获取所有品种名称并将它们保存在包含品种作为键和 URL 图像(我通过对 API 的另一个获取请求获得)作为值的新数组数组。
我已经尝试了两个单独的函数,一个是使用 useState() 将品种存储到一个列表中,这有效,同时,在我的组件内部调用函数,该函数使用 . map 方法等。最后一部分不起作用。
const BreedSelectorBox: FunctionComponent = () => {
const [breeds, setBreeds] = useState<Array<string>>([]);
const fetchBreedsList = async () => {
const res: AxiosResponse = await axios.get(
"https://dog.ceo/api/breeds/list/all"
);
const breedList: Array<string> = [];
for (const [key, value] of Object.entries(res.data.message)) {
breedList.push(key);
}
const breedListImages: string[] = breedList.map(async (breed) => {
const image: string = await axios
.get(`https://dog.ceo/api/breed/${breed}/images/random`)
.then((res) => res.data.message);
return { key: breed, value: image };
});
// setBreeds(breedList);
console.log(breedListImages);
};
const fetchBreedRandomImage = async (breed: string) => {
const res: AxiosResponse = await axios.get(
`https://dog.ceo/api/breed/${breed}/images/random`
);
return res.data.message;
};
return (
<Box
第一次尝试时,我使用了我的 breeds 变量的结果,并使用 .map 遍历了每个品种,希望添加 fetchBreedRandomImage() 函数并获得图像 URL/string 但我没有没有得到任何东西,因为该函数显然 returns 是一个承诺而不是字符串,因此没有显示图像。
我的下一个想法是使用 breedListImages() 函数,我试图在我的组件之外执行此操作并创建如上所述的数组数组,它 returns 与我使用的类似无法工作或不知道如何:
关于如何解决我的问题有什么想法吗?此外,如果您发现我的 Typescript 有任何问题,那是我的第一次尝试,所以您已收到警告!
在尝试@Phil solution/function 之后非常完美,谢谢你:
我收到此错误:
我还使用这些代码片段将图像渲染到我的组件:
<ImageList
sx={{
width: 500,
height: 450,
// Promote the list into its own layer in Chrome. This costs memory, but helps keeping high FPS.
transform: "translateZ(0)",
}}
rowHeight={200}
gap={1}
>
{breeds &&
breeds.map((breed) => {
const cols = breed.featured ? 2 : 1;
const rows = breed.featured ? 2 : 1;
/// try to ignore those lines with const cols and rows
return (
<ImageListItem key={breed.key} cols={cols} rows={rows}>
<img
src={breed.value}
alt={breed.key}
// loading="lazy"
width={250}
height={200}
/>
<ImageListItemBar
sx={{
background:
"linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, " +
"rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)",
}}
title={breed}
position="top"
actionIcon={
<IconButton
sx={{ color: "white" }}
aria-label={`star ${breed}`}
>
<StarBorderIcon />
</IconButton>
}
actionPosition="left"
/>
</ImageListItem>
);
})}
</ImageList>
我该如何摆脱困境?再次感谢!
解决我上一个错误的方法是在我的代码中正确设置我的 src、alt 等属性,所以 Phil 的回答没有错!再次感谢!!
您输入的内容不正确。 breedListImages
不是 string[]
但实际上...
Array<Promise<{ key: string, value: string }>>
这是因为 async
的功能类似于您的 .map()
回调 return 承诺。
您需要使用 Promise.all() 来等待所有这些承诺在设置您的状态之前解决。
这是一个清理过的版本,定义了一些更好的接口...
// this matches `{ key: breed, value: image }` from your question
interface DogBreed {
key: string,
value: string
}
interface ListAllResponse {
message: {
[ key: string ]: string[]
}
}
interface ImageResponse {
message: string
}
const BreedSelectorBox: FunctionComponent = () => {
// state is an array of DogBreed types
const [breeds, setBreeds] = useState<DogBreed[]>([]);
const fetchBreedsList = async () => {
// fetch all breeds. Axios requests can be typed for the response
const { data: { message: allBreeds } } = await axios.get<ListAllResponse>(
"https://dog.ceo/api/breeds/list/all"
);
// extract keys from the ListAllResponse.message
const keys = Object.keys(allBreeds)
// resolve images and create DogBreed objects
const dogBreeds = await Promise.all(keys.map(async key => {
const { data: { message: value } } = await axios.get<ImageResponse>(
`https://dog.ceo/api/breed/${encodeURIComponent(key)}/images/random`
)
return { key, value }
}))
// console.log(dogBreeds)
setBreeds(dogBreeds)
};
我目前正在使用 Typescript 使用 NextJS 应用程序,我的问题出在功能方面:我正在使用 Dog API 获取所有品种名称并将它们保存在包含品种作为键和 URL 图像(我通过对 API 的另一个获取请求获得)作为值的新数组数组。
我已经尝试了两个单独的函数,一个是使用 useState() 将品种存储到一个列表中,这有效,同时,在我的组件内部调用函数,该函数使用 . map 方法等。最后一部分不起作用。
const BreedSelectorBox: FunctionComponent = () => {
const [breeds, setBreeds] = useState<Array<string>>([]);
const fetchBreedsList = async () => {
const res: AxiosResponse = await axios.get(
"https://dog.ceo/api/breeds/list/all"
);
const breedList: Array<string> = [];
for (const [key, value] of Object.entries(res.data.message)) {
breedList.push(key);
}
const breedListImages: string[] = breedList.map(async (breed) => {
const image: string = await axios
.get(`https://dog.ceo/api/breed/${breed}/images/random`)
.then((res) => res.data.message);
return { key: breed, value: image };
});
// setBreeds(breedList);
console.log(breedListImages);
};
const fetchBreedRandomImage = async (breed: string) => {
const res: AxiosResponse = await axios.get(
`https://dog.ceo/api/breed/${breed}/images/random`
);
return res.data.message;
};
return (
<Box
第一次尝试时,我使用了我的 breeds 变量的结果,并使用 .map 遍历了每个品种,希望添加 fetchBreedRandomImage() 函数并获得图像 URL/string 但我没有没有得到任何东西,因为该函数显然 returns 是一个承诺而不是字符串,因此没有显示图像。
我的下一个想法是使用 breedListImages() 函数,我试图在我的组件之外执行此操作并创建如上所述的数组数组,它 returns 与我使用的类似无法工作或不知道如何:
关于如何解决我的问题有什么想法吗?此外,如果您发现我的 Typescript 有任何问题,那是我的第一次尝试,所以您已收到警告!
在尝试@Phil solution/function 之后非常完美,谢谢你:
我还使用这些代码片段将图像渲染到我的组件:
<ImageList
sx={{
width: 500,
height: 450,
// Promote the list into its own layer in Chrome. This costs memory, but helps keeping high FPS.
transform: "translateZ(0)",
}}
rowHeight={200}
gap={1}
>
{breeds &&
breeds.map((breed) => {
const cols = breed.featured ? 2 : 1;
const rows = breed.featured ? 2 : 1;
/// try to ignore those lines with const cols and rows
return (
<ImageListItem key={breed.key} cols={cols} rows={rows}>
<img
src={breed.value}
alt={breed.key}
// loading="lazy"
width={250}
height={200}
/>
<ImageListItemBar
sx={{
background:
"linear-gradient(to bottom, rgba(0,0,0,0.7) 0%, " +
"rgba(0,0,0,0.3) 70%, rgba(0,0,0,0) 100%)",
}}
title={breed}
position="top"
actionIcon={
<IconButton
sx={{ color: "white" }}
aria-label={`star ${breed}`}
>
<StarBorderIcon />
</IconButton>
}
actionPosition="left"
/>
</ImageListItem>
);
})}
</ImageList>
我该如何摆脱困境?再次感谢!
解决我上一个错误的方法是在我的代码中正确设置我的 src、alt 等属性,所以 Phil 的回答没有错!再次感谢!!
您输入的内容不正确。 breedListImages
不是 string[]
但实际上...
Array<Promise<{ key: string, value: string }>>
这是因为 async
的功能类似于您的 .map()
回调 return 承诺。
您需要使用 Promise.all() 来等待所有这些承诺在设置您的状态之前解决。
这是一个清理过的版本,定义了一些更好的接口...
// this matches `{ key: breed, value: image }` from your question
interface DogBreed {
key: string,
value: string
}
interface ListAllResponse {
message: {
[ key: string ]: string[]
}
}
interface ImageResponse {
message: string
}
const BreedSelectorBox: FunctionComponent = () => {
// state is an array of DogBreed types
const [breeds, setBreeds] = useState<DogBreed[]>([]);
const fetchBreedsList = async () => {
// fetch all breeds. Axios requests can be typed for the response
const { data: { message: allBreeds } } = await axios.get<ListAllResponse>(
"https://dog.ceo/api/breeds/list/all"
);
// extract keys from the ListAllResponse.message
const keys = Object.keys(allBreeds)
// resolve images and create DogBreed objects
const dogBreeds = await Promise.all(keys.map(async key => {
const { data: { message: value } } = await axios.get<ImageResponse>(
`https://dog.ceo/api/breed/${encodeURIComponent(key)}/images/random`
)
return { key, value }
}))
// console.log(dogBreeds)
setBreeds(dogBreeds)
};