Updating Startup File, Wallet Connect & Main Menu

Prettier config

Preparing the startup file

The first thing you have to do after creating the React App is to take a look inside the src directory. There you will find a file named App.js . This is the file that gives you control over the application’s startup. Initially, it returns the app’s main HTML content, having included the <ConnectWallet/> and <ContractCallVote/> tags. These refer to the components having the same names which can be found inside the components directory. For our app we will only use <ConnectWallet/>, which is responsible for the wallet connection, so you have to remove unnecessary code lines. After removal, the App.js return should look like this:

return (
  <div className="App">
    <ConnectWallet />
  </div>
)

Initializing ConnectWallet & MainMenu

Update the Connect Wallet

Having App.js modified, we have to move on what happens inside the ConnectWallet component. Once you are here, you can see the authenticate() function, containing showConnect() . Here we will need to modify the app’s name from Stacks React Starter to NFT Web App Integration. Now you are all set and ready for the fun!

As you certainly have seen before, applications have a main page, and we will build one to manage our app’s functionality. To make this possible, you will need some prerequisites. The first one is a constant to check the ConnectWallet component loaded successfully. You should do this using the react State hook, which will be imported inside ConnectWallet.

const [mounted, setMounted] = useState(false);

We will place the constant inside the ConnectWallet component and it will look like this:

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

​As you see, the mounted constant is a boolean. You will need to attach a setMounted function which allows you to update your mounted constant’s initial value using the State hook imported before. As you have seen before, we are initializing the mounted constant with the false value, because we assume that when ConnectWallet component is returned from App.js, its thread is not completed and we can not move forward. To check the thread completion, we will definitely need to use the react Effect hook . Summarily, by using the Effect hook inside ConnectWallet we can tell React to execute certain lines after successfully rendering the component we refer to. The result inside ConnectWallet component will look like this:

const [mounted, setMounted] = useState(false);
useEffect(() => setMounted(true), []);

Now we make sure the component’s content was successfully loaded just when the mounted’s value is set true. As we decided before, we will need a MainMenu component. Having implemented the mounted constant, we can jump to creating conditionals for returning the MainMenu component right after ConnectWallet accomplishes its mission. Although, you may be asking what our app will do unless the ConnectWallet component is mounted. The main returned content of the component we refer to should look like this:

return (
  <header className="App-header">
    <h1>Integrate NFTs Into GameFi</h1>
      <button className="Connect" onClick={authenticate}>
        Connect Wallet
      </button>
      <a className="App-link" href="<https://stacksdegens.com/>" target="_blank">
        Build by Stacks Degens
      </a>
    </header>
);

In brief, as the ConnectWallet is still working on its execution thread, React will return the specific HTML content from above. By doing this, we made sure the user will receive content while the app is loading. The <button className="Connect" onClick={authenticate}> makes possible the user’s authentication by the Hiro Wallet. As it is clear to see, the button’s event handler is the authenticate() function we have seen before. When do we want to let the user pass through the authentication process? Certainly, when he is signed out. We can get the opposite state if the user is signed in and the component is mounted.

Introduce the Main Menu

Based on the above assumption, we will start building the conditional for returning the MainMenu component. Please make sure you create a MainMenu.js file in the src/components directory that looks like this:

export const MainMenu = () => {}

Above we have exported the MainMenu component, to make possible to return it inside the ConnectWallet component, but for this we will need to import it where we need it, too. In the ConnectWallet component:

import { MainMenu } from './MainMenu';

This is how we will build the conditional, returning the corresponding <MainMenu/> component inside ConnectWallet:

if (mounted && userSession.isUserSignedIn()) {
  return (
    <div>
      <MainMenu />
    </div>
  );
}

Let’s analyze the above code snippet. The first part of the condition is clear, referring to our mounted const. This will be true when the constant’s value is set on true. But what happens to the other side of our condition? You probably have already found out these statements inside ConnectWallet:

import { AppConfig, showConnect, UserSession } from '@stacks/connect';

const appConfig = new AppConfig(['store_write', 'publish_data']);
export const userSession = new UserSession({ appConfig });

We can see above that userSession is nothing more than a session we create for each user, when getting on the wallet authentication stage. This gives us permission to check whether the user has completed the authentication step, using userSession.isUserSignedIn(). Exporting it will allow us to access its value, modify it and permanently taking it into account inside ConnectWallet conditional. These having been said, the condition will be true only if the ConnectWallet has been mounted AND the user is signed in. This is the appropriate environment to returning our MainMenu component. If at least one of these two conditions is false, ConnectWallet will continue to return its default return content we have discussed above.

Developing the Main Menu

We are ready to get straight to our MainMenu. We made sure the user can reach this stage only after connecting his wallet. What if he wants to disconnect his wallet? Making this possible implies moving the disconnect() function from ConnectWallet to MainMenu. This function should be an event handler for a <button> if we want to give it functionality. For this, we have to return the following <button> tag:

<button className="Connect" onClick={disconnect}>
  Disconnect Wallet
</button>

The MainMenu should look like this:

import { userSession } from './ConnectWallet';

export const MainMenu = () => {
  const disconnect = ()  =>{
    userSession.signUserOut('/');
  }
  
  const userAddress = userSession.loadUserData().profile.stxAddress['testnet'];

  return (
    <div>
      <header className="App-header">
        <h1>Integrate NFTs Into GameFi</h1>
        <h6>{`Current user address: ${userAddress}`}</h6>
	<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>
  );
};

As you surely have guessed, we import the userSession to the MainMenu. We will need it in case the user wants to sign out . Also, we want the user to be able to see his userAddress. For this, we will use the same imported userSession constant.

By the userSession.loadUserData().profile.stxAddress['testnet']} tag we are returning the user’s Stacks address for the testnet network. We are doing this becausewe use the testnet network in our example.

If you want to go the extra mile, you can create another .js file inside constants directory called network.js. There you should create a constant called network, export it, and use it wherever you need inside the project, surely after importing it.

This is the branch with the changes done:

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

Last updated