Home > Net >  Maximum recursive updates exceeded in component
Maximum recursive updates exceeded in component

Time:06-09

I am trying to build this pretty simple fetching function:

const fetchUnstakedNFTs = async (): Promise<void> => {
    if (wallet.value && wallet.value.connected && publicKey.value) {
      const tokenAccountsFromWallet =
        await connection.getParsedTokenAccountsByOwner(publicKey.value, {
          programId: new PublicKey(
            "TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA"
          ),
        });
      // Define and/or reset tokenAccounts Array
      const tokenAccounts: {
        pubkey: PublicKey;
        account: AccountInfo<ParsedAccountData>;
      }[] = [];

      for (const account of tokenAccountsFromWallet.value) {
        const metadata = await getMetadata(
          account.account.data.parsed.info.mint
        );
        // Add NFTs with matching creator and amount === 1 to tokenAccounts
        if (
          metadata &&
          metadata.creators &&
          metadata.creators[0].address === nftCreator.toString() &&
          account.account.data.parsed.info.tokenAmount.amount === "1"
        ) {
          tokenAccounts.push(account);
        }
      }

      // Add tokenAccounts to unstakedNFTs if they are not already in there
      for (const tokenAccount of tokenAccounts) {
        const metadata = await getMetadata(
          tokenAccount.account.data.parsed.info.mint
        );
        if (
          metadata &&
          metadata.creators &&
          metadata.creators[0].address == nftCreator.toString()
        ) {
          const { data } = await axios.get(metadata.uri);
          const newNFT = {
            name: data.name,
            symbol: metadata.symbol,
            image: data.image,
            mintId: tokenAccount.account.data.parsed.info.mint,
            tokenAccount: tokenAccount.pubkey.toString(),
            isStaking: false,
            isSelected: false,
          };
          // check if unstakedNFTs contains the NFT already
          if (
            !unstakedNFTs.value.find(
              (nft) =>
                nft.mintId === newNFT.mintId &&
                nft.tokenAccount === newNFT.tokenAccount
            )
          ) {
            // if it doesnt, add it to unstakedNFTs
            console.log("Adding NFT to unstakedNFTs", newNFT);
            unstakedNFTs.value.push(newNFT);
          }
        }
      }
    }
  };

But I am getting this warning:

Maximum recursive updates exceeded in component . This means you have a reactive effect that is mutating its own dependencies and thus recursively triggering itself. Possible sources include component template, render function, updated hook or watcher source function.

instrumentations.<computed> @ reactivity.esm-bundler.js?89dc:439
fetchUnstakedNFTs @ createWalletStore.ts?a4c6:344

I have no Idea what to try anymore. Looking at this part of the warning: fetchUnstakedNFTs @ createWalletStore.ts?a4c6:344

You can see that it points to this line of my function (line 344):

unstakedNFTs.value.push(newNFT);

Here the NFTPane.vue Component:

<template>
  <div >
    <div  v-if="wallet.fetching && nfts.length == 0">
      <div v-for="item in shimmerArray" :key="item" >
      </div>
    </div>
    <div v-else >
      <button :disabled="nft.isStaking" @click="selectNFT(nft)" v-for="nft in nfts" :key="nft.image"
        >
        <img
          :
          :src="nft.image" />
        <div
          >
          #{{ getNFTNumber(nft.name) }}
        </div>
      </button>
    </div>
    <div >
      <button  @click="onStake()">
        <span>
          {{ stakeType == StakeType.unstaked ? 'Stake' : 'Unstake' }}
        </span>
      </button>
      <button  @click="onStakeAll()">
        <span>
          {{ stakeType == StakeType.unstaked ? 'Stake All' : 'Unstake All' }}
        </span>
      </button>
      <button v-if="stakeType == StakeType.staked" @click="claimAllRewards()" >
        <span>
          Claim Rewards
        </span>
      </button>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { defineProps, ref } from 'vue';
import { PublicKey } from '@solana/web3.js';
import { NFT, StakeType } from '@/types/types';
import { useWallet, useAnchorWallet } from '@/composables/useWallet/index';
import { claimNFTRewards } from '@/plugins/utils/claim_rewards/src/claim_rewards'
import { connection, stakePoolID } from '@/constants';
import { createToast } from '@/plugins/toast/createToast';
import { unstakeNFT } from '@/plugins/utils/unstake/src/unstake';
import { stakeNFT } from '@/plugins/utils/stake/src/stake';
import { getNFTNumber } from '@/composables/utils';
// import FadeLoader from 'vue-spinner/src/FadeLoader.vue';

const props = defineProps<{
  nfts: NFT[],
  stakeType: StakeType,
}>();

const wallet = useWallet();
const anchorWallet = useAnchorWallet();
const shimmerArray = Array(9)

const selectNFT = async (nft: NFT) => {
  nft.isSelected = !nft.isSelected;
}

const claimAllRewards = async () => {
  if (anchorWallet.value) {
    claimNFTRewards(
      connection,
      anchorWallet.value,
      {
        stakePoolId: stakePoolID,
        nfts: wallet.stakedNFTs.value,
        callback: () => {
          createToast('Successfully claimed rewards', {
            type: 'success',
          });
        }
      }
    );
  }
};

const onStakeAll = async () => {
  if (props.stakeType == StakeType.staked) {
    wallet.stakedNFTs.value = wallet.stakedNFTs.value.map(stakedNFT => {
      stakedNFT.isSelected = true;
      return stakedNFT;
    });
  }
  else {
    wallet.unstakedNFTs.value = wallet.unstakedNFTs.value.map(unstakedNFT => {
      unstakedNFT.isSelected = true;
      return unstakedNFT;
    });
  }
  await onStake();
}

const onStake = async () => {
  const alertIndex = ref(0);
  if (anchorWallet.value) {
    if (StakeType.staked == props.stakeType) {
      const nfts = wallet.stakedNFTs.value.filter(stakedNFT => stakedNFT.isSelected);
      nfts.forEach((nft) => nft.isStaking = true)
      wallet.staking.value = true;
      try {
        await unstakeNFT(connection, anchorWallet.value, {
          stakePoolId: stakePoolID,
          originalMintId: nfts.map(nft => new PublicKey(nft.mintId)),
          callback: () => {
            alertIndex.value  ;
            if (nfts.length === 1) {
              createToast("Successfully Unstaked NFT", {
                type: "success",
                transition: "zoom",
                timeout: 5000,
                showIcon: true,
              });
            }
            else {
              createToast(`${alertIndex.value}/${nfts.length} Successfully Unstaked NFT`, {
                type: "success",
                transition: "zoom",
                timeout: 5000,
                showIcon: true,
              });
            }
            if (alertIndex.value == nfts.length) {
              alertIndex.value = 0;
              wallet.staking.value = false;
            }
            wallet.fetchNFTs();
          },
        });
      }
      catch (e) {
        wallet.staking.value = false;
        nfts.forEach((nft) => nft.isStaking = false)
      }
    } else {
      const nfts = wallet.unstakedNFTs.value.filter(stakedNFT => stakedNFT.isSelected);
      nfts.forEach((nft) => nft.isStaking = true)
      wallet.staking.value = true;
      try {
        await stakeNFT(connection, anchorWallet.value, {
          stakePoolId: stakePoolID,
          nfts: nfts,
          callback: () => {
            alertIndex.value  ;
            if (nfts.length === 1) {
              createToast("Successfully Staked NFT", {
                type: "success",
                transition: "zoom",
                timeout: 5000,
                showIcon: true,
              });
            }
            else {
              createToast(`${alertIndex.value}/${nfts.length} Successfully Staked NFT`, {
                type: "success",
                transition: "zoom",
                timeout: 5000,
                showIcon: true,
              });
            }
            if (alertIndex.value == nfts.length) {
              alertIndex.value = 0;
              wallet.staking.value = false;
            }
            wallet.fetchNFTs();
          }
        })
      }
      catch (e) {
        wallet.staking.value = false;
        nfts.forEach((nft) => nft.isStaking = false)
      }
    }
    await wallet.fetchNFTs();
  }
}
</script>

CodePudding user response:

After hours and hours of trying I found out that I just had to remove the getNFTNumber(nft.name) function from my <NFTPane> Component

  • Related