Search code examples
javascriptarraysreactjsindexingfetch

Fetching images from an array of URLs and mapping them into new array (ReactJS)


In my project, I have to fetch 20 images from The Met Digital Collection and display three random images.

In order to do that I tried to put every link into an array and fetching them with promise all.

The problem is that every image gets stored in the same value so I can´t call for a specific image in that array. Is it possible to get an index from "const [url, setURL]" or can I give the images an index at the same time as "setURL(data.primaryImage)"?

I am grateful for any help I can get! :)

const [url, setURL] = useState([]);

useEffect(() => {
  const urls = [
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/250940',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/20622',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/436625',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/436444',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/436509',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/359245',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/459090',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/333933',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/333916',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/466350',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/44831',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/383010',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/202660',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/406317',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/337349',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/503448',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/12617',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/248662',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/435805',
    'https://collectionapi.metmuseum.org/public/collection/v1/objects/438545',
  ];

  Promise.all(
    urls.map((url) =>
      fetch(url)
        .then((response) => response.json())
        .then((data) => setURL(data.primaryImage))
        .catch((error) => console.log('There was a problem!', error))
    ),
    []
  );
}, []);

Solution

  • Use Promise.all(...).then(values => setURLs(values)) to atomically set your URLs array.

    Here's a Live Example.

    Code + some refactoring:

    const [urls, setURLs] = useState([]);
    
    useEffect(() => {
      const urls = [
        250940,
        20622,
        436625,
        436444,
        436509,
        359245,
        459090,
        333933,
        333916,
        466350,
        44831,
        383010,
        202660,
        406317,
        337349,
        503448,
        12617,
        248662,
        435805,
        438545
      ].map(
        (itemId) =>
          `https://collectionapi.metmuseum.org/public/collection/v1/objects/${itemId}`
      );
    
      Promise.all(
        urls.map((currUrl) =>
          fetch(currUrl)
            .then((response) => response.json())
            .then((data) => data.primaryImage)
            .catch((error) => console.log("There was a problem!", error))
        )
      ).then((fetchedUrls) => setURLs(fetchedUrls));
    }, []);