1

This might be the best place to ask this.

I'm having an infinite loop issue when fetching my NFT's json URI. My main issue was being able to display my NFT's name on the screen but now i'm getting an infinite loop. My function that does the fetching keeps getting called.

What I've tried:

  • useEffect [] WITH THE ARRAY THING
  • Moving the API call function outside of the components scoop
  • UseCallback
  • Async

Link to my Stack overflow question that helped me display metadata

Could the Drizzle component be getting re-render ? And causing an infinite loop?

What's being rendered on the Browser.

export default ({ drizzle, drizzleState }) => { 
  return (
    <div className="App">

      <ContractData
        drizzle={drizzle}
        drizzleState={drizzleState}
        contract="MyContract"
        method="totalSupply"
        labels="length"
        render={(totalSupply) => {
          const emptyArray = [];
          const arrayLength = Number(totalSupply);
          for(let i=0;i<arrayLength;i++){ emptyArray.push('') }
          if(emptyArray.length === 0) {
            return (
              <Jumbotron className="no-artwork">
                Nothing to see.
              </Jumbotron>
            )
          }
          return (
              <div className="collection-container">
                  {emptyArray.map(( _, index) => {
                    return (
                      <ContractData
                        key={index}
                        drizzle={drizzle}
                        drizzleState={drizzleState}
                        contract="MyContract"
                        method="tokenByIndex"
                        methodArgs={[arrayLength - 1 - index]}
                        render={(tokenId) => (
                          <>
                            <DisplayImage tokenId={tokenId} drizzle={drizzle} drizzleState={drizzleState} />
                          </>
                        )}
                      />
                    )}
                  )}
              </div>
            );
        }}
      />
  <div/>
 )};

DisplayImage component outside of export and what is rendering the images and metadata.

const DisplayImage = (NftData) => {
  const [nftMetadata ,setNftMetadata] = useState();

  useEffect(() => {
    setNftMetadata(GetURI(NftData))
  }, [GetURI,NftData]);
  
  return (
    <div>

      <ContractData
        drizzle={NftData.drizzle}
        drizzleState={NftData.drizzleState}
        contract="MyContract"
        method="CID"
        methodArgs={[NftData.tokenId]}
        render={(cid) =>  {
            return(
              <div className="token-container">
                <h2>{nftMetadata.name}</h2>
                <img className="artwork" width="250px" src={`https://ipfs.fleek.co/ipfs/${cid}`} />
              </div>
              )
      
          }}
      />

    </div>
  );

} 

Function fetching URI

I only want this to be called once per NFT , but something is causing an infinite loop. Am I missing something with useEffect or could it really be Drizzle?

const GetURI = async (data) => {
  
  const nftURI = await data.drizzle.contracts.MyContract.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 data || '';
    })
    .catch(err => {
      return console.log(err);
  });
  
};

I'm brainstorming a way to do useEffect inside export.

0

Your useEffect(...) function sets state, which will cause the component to be re-rendered, calling the function again, which will set state and so on...

To fix this, either only set the state if the value from GetURI(...) is different to nftMetadata or convert the component to a class and do this in componentDidMount().

0

Found my answer if anyone needs this in the future.



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>
})

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.