Rendered more hooks than during the previous render

Hi I am trying to get the price of an array of nfts however having this line const {data: nftPrice} = useEvmNFTLowestPrice({address: AppTokens[i].tokenAddress, chain: "5", marketplace:"opensea"}) within the for loop causes issues. Any ideas on how to do this differently?

const price = 0
  
    for(let i = 0 ; i< AppTokens.length; i ++)
    { 
      const {data: nftPrice} = useEvmNFTLowestPrice({address: AppTokens[i].tokenAddress, chain: "5", marketplace:"opensea"})
      const json = nftPrice.toJSON()
      const value = parseInt(ethers.utils.formatUnits(json.price)*AppTokens[i].time)
      price += value
    }
    console.log(price)

Hi, a note here. This endpoint is working only with NFTs from mainnet.

You need to make sure the hook is at the top level or inside an useEffect

  useEffect(() => {
    AppTokens.forEach((token, index) => {
      const { data: nftPrice } = useEvmNFTLowestPrice({
        address: token.tokenAddress,
        marketplace: "opensea",

      setPrices( /* add to prices */);
    });
  }, [AppTokens]);

// do something with the price after that 

Thanks, I have followed the above but I get the following error @Iulian

Invalid hook call. Hooks can only be called inside of the body of a function component. 

This is my useeffect

useEffect(() => {
      AppTokens.forEach((token, index) => {
        const { data: nftPrice } = useEvmNFTLowestPrice({
          address: "0xBC4CA0EdA7647A8aB7C2061c2E118A18a936f13D",
          marketplace: "opensea",
          chain:"1"
      })
      setPrices(price += parseInt(ethers.utils.formatUnits((nftPrice.toJSON()).price)*token.time));
    }, [AppTokens])})

Hi @CleanMcGerk

Here are few suggestions for your code.

1.Move the useEvmNFTLowestPrice outside useEffect and destruct the fetch function form the hook

const { data: nftPrice, fetch } = useEvmNFTLowestPrice()

You can’t call react hooks inside another function so replace your code logic to use this fetch function. fetch also accepts the same params as the hook.

2.You will need to create another useEffect for using setPrices. The data fetched from the useEvmNFTLowestPrice is stored in nftPrice which is a state variable. So using the useEffect is a better solution.

useEffect(() => {
      setPrices(price += parseInt(ethers.utils.formatUnits((nftPrice.toJSON()).price)*token.time));
    }, [nftPrice])})

And I am not sure if your setPrices with += will work as expected. In case if it fails you can try to save them as an array state variable and use a different function to sum them.

Thanks noted. However token.time does not exist outside of the function

    var price = 0
    const [timeous, setTime]=useState()
    const {data: nftPrice, fetch: getPrice, isFetching} = useEvmNFTLowestPrice()
    

    
      AppTokens.forEach((token, index) => {
       getPrice({
          address: token.tokenAddress,
          marketplace: "opensea",
          chain:"1"
      })
      setTime(token.time)
})
useEffect(()=>{
  if(nftPrice != undefined){
    price += parseInt(ethers.utils.formatUnits((nftPrice.toJSON()).price)*timeous);
    console.log(timeous)
  }
  
},[nftPrice])
1 Like

As long as it works you can update it as per your requirement :grinning_face_with_smiling_eyes:

Yes understood. I mentioned it because my solution brought about the Too many re-render error and Im unsure as to how to get around it

Are you still seeing Too many re-render or is it solved?

This usually occurs when you are updating a state variable or calling a function directly in the react function scope {} They should be handled within another function or useEffect etc…