-1

So I’m unable to load images from https://thecatapi.com/. When I try to console log the response in fetchCatImages, I get an array. When I console log the images in App.js, I get a pending promise with PromiseState: “fulfilled” and PromiseResult: Array(5). Can someone tell me what I’m doing wrong here?

EDITED: So I now understand async await will always return a Promise. I read through How do I return the response from an asynchronous call? but am still unsure how to get the data to display on App.js.

import React from 'react';
import './App.css';

async function fetchCatImages() {
    let images = [];
    await fetch('https://api.thecatapi.com/v1/images/search?limit=5')
        .then((res) => res.json())
        .then((data) => (images = data))
        .catch((e) => {
            console.error('fetch failed!');
            console.error(e);
        });
    console.log('file: App.js ~ line 16 ~ fetchCatImages ~ images', images); 
    // logs show an Array with 5 objects

    return images;
}

function App() {
    const images = fetchCatImages();
    console.log('App.js ~ line 7 ~ App ~ images', images);
    // logs shows Promise {pending}, PromiseState: “fulfilled”, PromiseResult: Array(5) 

    return (
        <>
            {!images.length ? (
                <h3>There are no cats</h3>
            ) : (
                {images.map(({ id, url }) => (
                    <div key={id}>
                        <img src={url} height={50} width={50} />
                    </div>
                ))}
            )}
        </>
    );
}

export default App;

I also tried using try catch instead without async await and still get the same problem.

function fetchCatImages() {
    let images = [];

    try {
        images = fetch('https://api.thecatapi.com/v1/images/search?limit=5').then((res) => res.json());
    } catch (e) {
        console.error('fetch failed!');
        console.error(e);
    }

    return images;
}
Etep
  • 2,721
  • 4
  • 17
  • 28
  • 1
    `async` function, by *[definition](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function#return_value)*, always returns a Promise – Jaromanda X Oct 22 '22 at 01:33
  • Thanks @JaromandaX for the hint. However, how do I get it to return the data in App.js? Reading Jared's link to https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call and still not quite sure how I can have it show the data instead of a Promise – Etep Oct 22 '22 at 02:07
  • I don't know enough about react to help with that. You just need to know that synchronous results are not possible from asynchronous code – Jaromanda X Oct 22 '22 at 02:18

1 Answers1

1

Try the following:

import React, { useState, useEffect } from "react";
import './App.css';

export default function App() {
  const [cats, setCats] = useState([]);

  useEffect(() => {
    const fetchCatImages = async () => {
      await fetch("https://api.thecatapi.com/v1/images/search?limit=5")
        .then((res) => res.json())
        .then((data) => setCats(data))
        .catch((e) => {
          console.error("fetch failed!");
          console.error(e);
        });
    };

    fetchCatImages();
  }, []);

  return (
    <>
      {cats.length ? (
        cats.map(({ id, url }) => (
          <div key={id}>
            <img src={url} height={50} width={50} />
          </div>
        ))
      ) : (
        <h3> There are no cats </h3>
      )}
    </>
  );
}
Ryan
  • 1,151
  • 5
  • 7
  • Although this does work, I am trying to make `fetchCatImages` into a useHook for react and that's why I created it as it's own function. Is there a reason I'm getting a promise instead of an Array? – Etep Oct 22 '22 at 01:25
  • Just move the state and `useEffect` to a `useCats` or whatever you want to call it custom hook, return the state and use the custom hook in your component. – ivanatias Oct 22 '22 at 02:03