Getting all the NFTs of an account over multiple addresses

Hi, I’m trying to get all the nfts an account has. I heard that Moralis.Web3API.account.GetNFTs will be deprecated in moralis nitro. So I’m trying to do it will multiple getNFTBalance calls like this:

const { getNFTBalances } = useNFTBalances();
const [nftCollection, setNftCollection] = useState([]);

useEffect(() => {
    const current_user = Moralis.User.current();
    const accounts = current_user.get("accounts")
    accounts.forEach(account => {
      getNFTBalances({
        params: {chain: "ropsten", address: account},
        onSuccess: (data) => {
          console.log("data", ...data.result);
          console.log("collection", ...nftCollection);
          setNftCollection([...nftCollection, ...data.result]);
        }
      })
    });
  }, [])

But when I do this nftCollection isn’t getting accumulated. I’m not the best with javascript. Any idea what the right way to do this would be.

1 Like

Hey, can you try also logging isFetching onSucess? Maybe its being onSucessed pre maturilly ?

Also because you are running this in a use effect you need to kind of change the way its being ran. The thing with useEffect is that it natively does not support promise calls such as the one above to do so with use effect you need to declare the function and then call it underneath.

useEffect(() => {
    async function fetchNfts() {
      const current_user = Moralis.User.current();
    const accounts = current_user.get("accounts")
    accounts.forEach(account => {
      await getNFTBalances({
        params: {chain: "ropsten", address: account},
        onSuccess: (data) => {
          console.log("data", ...data.result);
          console.log("collection", ...nftCollection);
          setNftCollection([...nftCollection, ...data.result]);
        }
      })
    }

    fetchNfts()
  }, [])

Try both lmk if it helps. :v:

Sure will do! I’m very new to react, really appreciate it

Hey so the

console.log("data", ...data.result);
console.log("collection", ...nftCollection);

are printing the right stuff. It’s just whichever one happens second is overriding the first. Is it possible there’s a closure issue going on? Like nftCollection is just staying as [] in the method?

Hey its because using set state in a use effect also works differently :sweat_smile:. Put it into a normal constant and lmk if the data is there if so we can work on the setState method.

Standard const works!

This did the trick:

const tempCollection = [];

  useEffect(() => {
    const current_user = Moralis.User.current();
    const accounts = current_user.get("accounts")
    accounts.forEach(account => {
      getNFTBalances({
        params: {chain: "ropsten", address: account},
        onSuccess: (data) => {
          tempCollection.push(...data.result);
          setNftCollection(tempCollection);
        }
      })
    });
  }, [])

:partying_face: yep that would work. For general knowledge the reason you can’t use set state for arrays within a use effect is because the two are running simultaneously so at the end the one that finishes last is overwrites. That’s why like you did above you use push, as push dosen’t over ride previous data. Hope this saves you a headache in the future.

Have a good day man✌️

Awesome, really appreciate it. Thanks :slight_smile:

Small update: change setNftCollection(tempCollection); -> setNftCollection([...tempCollection]);

  const tempCollection = [];
  useEffect(() => {
    const current_user = Moralis.User.current();
    const accounts = current_user.get("accounts")
    accounts.forEach(account => {
      getNFTBalances({
        params: {chain: "ropsten", address: account},
        onSuccess: (data) => {
          tempCollection.push(...data.result);
          setNftCollection([...tempCollection]);
        }
      })
    });
  }, []);