Search code examples
reactjsrxjscallbackfetchasynccallback

How to fetch api via looped callbacks with React functional components


So I have a 40+ loop that's calling another component to display images. Each image has an ID and with that ID I can get more information about the image like Name and description via another API call.

When DisplayImage gets called I want it to call another callback function that will send out API calls for that image's metadata, store it in a variable and display it as an H1 tag.

return (
 <div>

  {array.map(index) => {

   // Some Other Code That return a TokenID //

   <>
    {displayImage(tokenId)}
   </>
 
 </div>
})
 const displayImage = (tokenId) => {

  const imageName = GetURI(tokenId)

  return (
      <div className="token-container">
        <h1>{imageName}</h1>
        <img className="artwork" width="250px" src={`https://ipfs-asdf/${tokenId}`} />
      </div>
  )

 }

const GetURI = async (tokenId) => {

    const res = await fetch("https://api"+tokenId , {
        headers: {
          'Content-Type': 'application/json',
          'Accept': 'application/json'
        },
    }).then(data => {
      console.log(data)
      return data.json();
    })
    .then(data => {
      return (data.name || [])
    })
    .catch(err => {
      console.log(err);
    });
}

The data is being displayed on the console but now I'm running into an infinite loop issue that I know UseEffect can solve but I can't quite figure it out. I managed to display the data on the console with UseEffect using the [] attribute but don't know how to display the data. Any help would be amazing. Thank you!


Solution

  • I found the best way to go about it with everyones help on here so thanks!

    I put the GetURI function inside the show image component, and had a useEffect method call GetURI every time there was a new token ID, then I set a state variable to whatever was returned.

    No loops, no errors 👌

    
    
    const DisplayImage = (data) => {
    
      const [nftMetadata, setNftMetadata] = useState();
    
      const GetURI = async (data) => {
         const nftURI = await data.drizzle.contracts.Contract.methods.tokenURI(data.tokenId).call()
    
          await fetch(nftURI , {
            headers: {
              'Content-Type': 'application/json',
              'Accept': 'application/json',
              "Access-Control-Allow-Origin": "*"
            },
            })
            .then(data => {
              return data.json();
            })
            .then(data => {
              return setNftMetadata(data || []);
            })
            .catch(err => {
              return console.log(err);
          });
      });
    
      useEffect(() => {
        GetURI(data);
      }, [data.tokenId])   
      
      return (
        <div className="token-container">
    
         <h2>{nftMetadata.name}</h2>
         <img className="artwork" width="450px" src={`https://ipfs:/whatever/${nftMetadata.image}`} />
    
        </div>
      );
    
    };
    
    
    return (
     <div>
    
      {array.map(index) => {
    
       // Some Other Code That returns a TokenID //
    
       <>
        <DisplayImage address={drizzle.contractList[0].address} tokenId={tokenId} drizzle={drizzle} drizzleState={drizzleState}/>
       </>
     
     </div>
    })