使用 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)
  };