【问题标题】:fetching data from the Dog API using axios and saving data into a new array使用 axios 从 Dog API 获取数据并将数据保存到新数组中
【发布时间】:2022-02-17 03:29:24
【问题描述】:

我目前正在使用 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

在第一次尝试时,我使用了我的品种变量的结果,并使用 .map 遍历每个品种,希望添加 fetchBreedRandomImage() 函数并获取图像 URL/字符串,但我没有得到任何东西,因为该函数显然返回一个承诺而不是一个字符串,因此没有显示图像。

我的下一个想法是使用breedListImages() 函数,在该函数中我试图在我的组件之外执行此操作并创建一个如上所述的数组数组,它​​会返回类似我无法使用或无法使用的东西'不知道怎么做:

关于如何解决我的问题的任何想法?另外,如果您发现我的 Typescript 有任何问题,那是我的第一次尝试,因此您已收到警告!



在尝试了完美的@Phil 解决方案/功能并感谢您: 我收到了这个错误:

而且我还使用这些 sn-ps 代码将图像渲染到我的组件:

<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 的回答没有错!再次感谢!!

【问题讨论】:

    标签: reactjs typescript axios next.js


    【解决方案1】:

    您的输入不正确。 breedListImages 不是string[] 但实际上...

    Array<Promise<{ key: string, value: string }>>
    

    这是因为 async 函数类似于您的 .map() 回调返回承诺。

    在设置状态之前,您需要使用 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)
      };
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-11-15
      • 1970-01-01
      • 2015-05-22
      • 2022-01-15
      • 2019-12-22
      • 2021-10-21
      • 2021-09-22
      • 2019-06-27
      相关资源
      最近更新 更多