For Function 一直循环

For Function keeps looping

我的代码一直循环这部分代码的所有 ID,而我只希望它循环遍历帐户拥有的图片的 ID,假设某人拥有 ID 1 - 4,代码现在无限循环遍历这些数字并不断遍历它们并刷新图片而不给出 id 1,然后 2 等。:

function getMeta() {
    let nfts = []
    for(let i = 0; i < elfBalance; i++) {
        nftContract.tokenOfOwnerByIndex(currentAccount, i).then((result:string)=>{setId(result.toString())})
        nfts.push(<img id={tokenIds} width="128" height="128" alt='' src={"https://opensea.mypinata.cloud/ipfs/QmXuUzMCSybPdcySbn4h7F11hYAY3QkEQKeaDHtKPdZ38t/"+tokenIds+".png"} />)
      }
    return (
      <div>
        {nfts}
      </div>
    )
    
    }

我的整个代码:

import { ethers, utils , BigNumber} from "ethers";
import abi from '../web3/abi.json';
import './Inventory.css';
import { Button2 } from '../Button';
import Loadpics from './loadpics';

const contractAddress = "0x89e0A37218333b6dFd6785E33f0AFd913BD8406d"
const provider = new ethers.providers.Web3Provider(window.ethereum)
const nftContract = new ethers.Contract(contractAddress, abi , provider)



export default function Inventory() {

    const [currentAccount, setCurrentAccount] = useState('')
    const [elfBalance, setBalance] = useState('')
    const [tokenIds, setId] = useState('')

    const onClickConnect = () => {
      if(!window.ethereum) {
        console.log("please install MetaMask")
        return
      }
      provider.send("eth_requestAccounts", [])
      .then((accounts)=>{
        if(accounts.length>0) setCurrentAccount(accounts[0])
        console.log(accounts[0])
      })
      .catch((e)=>console.log(e))
    }
  
    const onClickDisconnect = () => {
      console.log("onClickDisConnect")
      setCurrentAccount(undefined)
    }
    
    useEffect(() => {
      if(!currentAccount || !ethers.utils.isAddress(currentAccount)) return
      //client side code
      if(!window.ethereum) return
      nftContract.balanceOf(currentAccount).then((result:string)=>{
        console.log(result)
        setBalance(result.toString())
      })
      

    },[currentAccount])

    function getMeta() {
        let nfts = []
        for(let i = 0; i < elfBalance; i++) {
            nftContract.tokenOfOwnerByIndex(currentAccount, i).then((result:string)=>{setId(result.toString())})
            nfts.push(<img id={tokenIds} width="128" height="128" alt='' src={"https://opensea.mypinata.cloud/ipfs/QmXuUzMCSybPdcySbn4h7F11hYAY3QkEQKeaDHtKPdZ38t/"+tokenIds+".png"} />)
          }
        return (
          <div>
            {nfts}
          </div>
        )
        
        }
            
  
    function renderMetamask() {
      if (!currentAccount || !ethers.utils.isAddress(currentAccount)) {
        return (
          <Button2 buttonStyle='btn--black' buttonSize='btn--small' className='connect-wallet' onClick={onClickConnect}>Connect Wallet</Button2>
        )
      } else {

        return(
          <div>
          {getMeta()}
          </div>
        )
      
    }
  }
  
    return(
    <div>
      {renderMetamask()}
    </div>
    )
}

我怀疑这里发生的事情是因为在 getMeta() 函数内部调用了 setId。

对 setId 的调用正在触发一个 re-render,最终导致 getMeta() 再次被调用,它再次调用 setId,触发另一个渲染并导致此循环。

这里可能需要在 useEffect 挂钩或类似的东西中发生。