Infinite loop using react Drizzle component

api-designdrizzleerc-721nftreact

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.

Best Answer

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().

Related Topic