GameFi
  • General Intro
  • 📃R & D
  • 💻Workshop
    • 🏎️NFT Web App Integration
      • 📄Prerequirements
      • Decentralized Storage
      • Smart Contract NFTs
      • Creating the React Dapp
      • Updating Startup File, Wallet Connect & Main Menu
      • Fetching NFTs, Stacks and Hiro API
      • Rendering NFTs owned
      • Selecting an NFT
      • Mapping Scenes
      • Creating the playable game
  • 🪙Trustless Rewards - M1
    • General idea
    • Flow Lobbies
    • Smart Contract
  • 🎨Customizable NFTs - M2
    • General Idea
    • Flow Customizable NFTs
    • Smart Contracts
      • Component
      • Customizable Wrapper
  • 🎁Lootbox on Chain - M3
    • General Idea
    • Tech Explained
    • Smart Contracts
      • Item
      • Lootbox
      • Lootbox Manager
  • 📝Message Signing
    • General Idea
    • GameFi Use Cases
    • App Explained
  • 🪵SFTs
    • General Idea & Base SFTs Static Deployments
    • Metadata Structure
    • Static Flow and Smart Contracts
    • Advanced SFTs Dynamic Deployments
    • Dynamic Flow and Smart Contracts
    • Dapp Integrating SFTs
      • Front End
      • Back End
    • Resources
  • ⚡Subnets
    • Overall for subnets
  • Roadmap
  • 💾Decentralized Storage
    • Gaia
    • Pinata
    • Host SFTs and NFTs into Pinata
    • Gaia integration to host game resources
  • 🔗External Knowledge
    • Getting Started
    • Hiro API
    • Stacks Docs
    • Clarity Book
    • Hiro Tutorials
Powered by GitBook
On this page
  • Create the needed states
  • Ensure waiting for the results by an async function
  • Render based on previous states
  • Render and return the NFTs by cases
  • This is the branch with the changes done:

Was this helpful?

  1. Workshop
  2. NFT Web App Integration

Rendering NFTs owned

All the code will be inserted into the MainMenu file

Now that we have a function to fetch all NFTs owned by the user, we want to give him an interface to see them. For this, we will have to store the complete list of ids using a constant inside the MainMenu component. We will be doing this using the same React State hook, so import it into MainMenu.js file. In addition, React Callback hook will be needed.

import React, { useEffect, useState, useCallback } from 'react';

Create the needed states

After importing the needed hooks, the next step is creating the constant to store the results. It will be a constant having attached a function to access its value by the State hook. We initialize it having the value of an empty list []. Also, we will need a boolean constant to record whether the API has responded and we can start rendering the results. When first getting on the MainMenu, obviously the results haven’t already been obtained, this is why we are initializing our constant being false.

const [NFTsOwned, setNFTsOwned] = useState([]);
const [hasRespondedNFTs, setHasRespondedNFTs] = useState(false);

Ensure waiting for the results by an async function

An arrow function that does the fetching steps will be needed, too. Keeping in evidence the fact that we need to wait for the response, the constant will be an asynchronous one. We are going to use the Callback hook because we only need to execute it once, unless the userAddress is modified. This is why userAddress is the unique Callback parameter.

const fetchNFTsOwned = useCallback(async () => {
  let localNFTsOwned = await getNFTsOwned(userAddress);
  setHasRespondedNFTs(true);
  if (localNFTsOwned) setNFTsOwned(localNFTsOwned);
  else setNFTsOwned([]);
}, [userAddress]);

As you see above, after waiting for the API’s response, we will set the hasRespondedNFTs constant’s value to true, meaning the interaction with the API has completed. If the local variable localNFTsOwned has at least one value, we will set the NFTsOwned constant’s value to the respective list of ids. If not, NFTsOwned will keep having the empty list [] value meaning the user does not own any NFTs. To give functionality to our fetchNFTsOwned constant, we will call it using the Effect hook previously explained. To cover any eventual changes to the user wallet balance, we are going to set an interval of 30 seconds in which the execution thread will be reloaded and the NFTs list will be updated.

useEffect(() => {
  fetchNFTsOwned();
  setInterval(() => {}, 30000);
}, [fetchNFTsOwned]);

Render based on previous states

Using NFTsOwned and hasRespondedNFTs states, we can build the cases in which the user can fit.

  1. The first one is when the API hasn’t responded yet. So we will return the corresponding <HTML> content which sends the message that the NFTs are still loading:

    {!hasRespondedNFTs && <h1> Loading NFTs... </h1>}
  2. The second one is when the API has responded, but the user does not own any NFTs:

    {hasRespondedNFTs && NFTsOwned.length == 0 && <h1> No NFTs available </h1>}
  3. The last one happens when the API has responded, and the user owns at least one NFT:

    {hasRespondedNFTs && NFTsOwned.length > 0 && (
      <div>
        <h2>Pick your NFT!</h2>
        {NFTsOwned.map((nftId) => (
          <span id={`nft${nftId}`} key={nftId}>
            <img
              src={`https://stacksgamefi.mypinata.cloud/ipfs/QmNz74TN66hgi9X4wZ1ch9hXKxaywG5soEQPMfDqEMLVsd/${nftId}.png`}
              alt={`duck ${nftId}`}
              width="50"
            ></img>
            {`NFT#${nftId}`}
          </span>
        ))}
      </div>
    )}

Render and return the NFTs by cases

The .map() does nothing but mapping each nftId from NFTsOwned to its corresponding <HTML> representation for the user experience. This way the user will see all the NFTs with the corresponding images and a suggestive name below each image. As you see above, the <img>'s src is written using the base Pinata url and the NFT’s id which could be found in NFTsOwned list. The final look of the returned content inside MainMenu will be the following:

return (
  <div>
    <header className="App-header">
      <h1>Integrate NFTs Into GameFi</h1>
      <h6>{`Current user address: ${userAddress}`}</h6>
      {!hasRespondedNFTs && <h1> Loading NFTs... </h1>}
      {hasRespondedNFTs && NFTsOwned.length == 0 && <h1> No NFTs available </h1>}
      {hasRespondedNFTs && NFTsOwned.length > 0 && (
        <div>
          <h2>Pick your NFT!</h2>
          {NFTsOwned.map((nftId) => (
            <span id={`nft${nftId}`} key={nftId}>
              <img
                src={`https://stacksgamefi.mypinata.cloud/ipfs/QmNz74TN66hgi9X4wZ1ch9hXKxaywG5soEQPMfDqEMLVsd/${nftId}.png`}
                alt={`duck ${nftId}`}
                width="50"
              ></img>
              {`NFT#${nftId}`}
            </span>
          ))}
        </div>
      )}
      <button className="Connect" onClick={disconnect}>
        Disconnect Wallet
      </button>
      <br></br>
      <a className="App-link" href="<https://stacksdegens.com/>" target="_blank">
        Build by Stacks Degens
      </a>
    </header>
  </div>
);

After completing this step, our MainMenu offers the user an interface where he can see all the NFTs he owns. Next, we want to give him the possibility to click each one in order to select it and finally play using it.

This is the branch with the changes done:

You can check the exact changes in this commit referring to them

PreviousFetching NFTs, Stacks and Hiro APINextSelecting an NFT

Last updated 2 years ago

Was this helpful?

💻
🏎️
https://github.com/BowTiedDeployer/workshop-nft-integration/tree/dapp/3-render-nftsgithub.com
branch dapp/3-render-nfts
https://github.com/BowTiedDeployer/workshop-nft-integration/commit/fefbfad13534d0c208dc3e990b876ac620062631github.com
commit fefbfad13534d0c208dc3e990b876ac620062631