Intro to dApp's: Create your dApp frontend w/React

Intro to dApp's: Create your dApp frontend w/React

·

7 min read

Featured on Hashnode

I get many dm's from dev's asking me how to get started with web3, hear such questions on twitter spaces and see the conversations on discord. It looks like so many developers are interested in the space.

If you are one of them, you're at the right place! In this post, I'll first try to explain the basics of web3 applications to provide an outline and then guide you through creating your dApp frontend with React.

Please note: In this article, we will be referring to dApp's on the Ethereum blockchain.


Intro to Decentralized App's (dApp's)

What is a dApp?

A dApp is just like any software application- any website or phone app. The difference is that the backend code runs on a decentralized network such as a peer to peer network or a blockchain.

So an application on Ethereum is a dApp.

What are the benefits?

  • Since the backend code(smart contracts) of a dApp is on a decentralized network, the dApp is free from control and can not be modified/removed by a centralized source. Developers and creators can trust the underlying infrastructure without worrying about being terminated or censored.

  • Once a smart contract is deployed to the Ethereum network, no one can change it. Therefore, users can trust how it will work since even the person deploying the contract can't change it.

  • All the smart contracts on Ethereum are public and accessible; it's an open-source ecosystem. This open-source nature allows for composability, so this means that you can re-use parts of the codes from others. You can look at all the smart contracts from Etherscan; here is an example smart contract.

A dApp only implies that the backend code(smart contract) is on a decentralized network. It's important to note that not all of the components of the application have to be decentralized. For example, the application developers decide where the frontend is hosted and where app data is stored.

The decentralized world advocates for making the entire technology stack decentralized and is building it right now!

What are dApp's used for?

Today the most popular categories for dApp's are gaming, financial services and digital goods.

Here are some popular dApp's on the Ethereum blockchain:

  • Uniswap-swap tokens and provide tokens for liquidity and rewards (Financial services)
  • Axie-play and earn with your avatars called "Axie" (Gaming)
  • Decenterland-collect and trade in the virtual world (Virtual world)
  • Open Sea : buy, sell, trade digital assets (Digital Goods)

There are probably more categories that we have not even discovered yet.

How can I use a dApp?

With most dApp's your cryptocurrency wallet is your first sign in. (Yay! No more username and passwords or connecting with other social media accounts.)

You basically need a cryptocurrency wallet and ETH-which is the native currency for the Ethereum blockchain. The wallet enables you to connect to the network and create a transaction, and you need the ETH to pay for the transaction.

Creating a dApp

A dApp consists of a backend (smart contract) and a frontend user interface in the most basic form. The frontend is the client-side, and the backend is the server-side of the application.

  • The backend of the dApp is the smart contract. Smart contracts are self-executing computer programs stored inside the blockchain, on Ethereum they are all open and accessible. You can look at them from Etherscan; here is an example of a smart contract. Another important note on smart contracts is that no one can change it once a smart contract is changed. Solidity is one of the most popular smart contract languages for Ethereum.

  • The frontend of the dApp can be written in any language that can talk to the backend. The frontend can then be hosted on a centralized service or a decentralized service.

In short, dApps are applications with a backend on a decentralized platform and a frontend that connects to it. To use a dApp, you need a cryptocurrency wallet and some cryptocurrency.


Create a dApp frontend w/React & ethers.js

In this project we will be creating a react project and connecting to our crypto wallet which is our interface to the blockchain.

Project Tools

  • Metamask Wallet: crypto wallet
  • React: JavaScript library for building user interfaces
  • ethers.js: Open source JavaScript Client library which contains the tools to talk to the Ethereum blockchain. (Another very popular option is web3.js. You can find a comparison of the two here.)

Please note: This project is only for the frontend of the application. When we want to add the backend piece we will need an Ethereum development environment. Hardhat and Truffle are popular Ethereum development environments. Additionally, to deploy the application to the network we would need to use a blockchain developer platform such as Alchemy or Infura .

Prerequisites

  1. Install metamask and create an account. Add the extension to your browser.
  2. Get node.js

Create D-app frontend

  1. Create a project folder and setup a react app

    npx create-react-app edas-dapp
    cd edas-dapp
    npm start
    
  2. Install the ethers.js libary

    with npm:

    npm install ethers
    

    with yarn:

    yarn add ethers
    
  3. The following code creates a button that the user can click which will prompt the user to connect to Metamask wallet. I have added the comments to explain what's going on. Add the following code to App.js.

    import './App.css';
    import { useEffect, useState } from 'react';
    
    const App = () => {
    
    //state variable to store user's public wallet 
    const [currentAccount, setCurrentAccount] = useState("");
    
    // check wallet connection when the page loads
    const checkIfWalletIsConnected = async () => {
    
     // access to window.ethereum
     const {ethereum} = window;
    
     //check if user has metamask 
     if(!ethereum) {
       alert("Make sure you have metamask");
       return;
     }
    
     //get the wallet account
     const accounts = await ethereum.request({method: 'eth_accounts'});
    
     //get the first account
     if(accounts.length !== 0){
       const account = accounts[0];
       console.log("Found account:", account);
    
       //set the account as a state 
       setCurrentAccount(account);
     }
     else{
       console.log("No account");
     }
    }
    
    // connect to wallet 
    const connectWallet = async () => {
     try {
       // get the wallet 
       const {ethereum} = window;
    
       // there is no wallet extension 
       if(!ethereum) {
         alert("Opps, looks like there is no wallet!");
         return;
       }
    
       const currentNetwork = ethereum.networkVersion;
       console.log("Current network", currentNetwork);
    
       // request access to account 
       const accounts = await ethereum.request({ method: "eth_requestAccounts"});
    
       //set the account in the state 
       setCurrentAccount(accounts[0]); 
    
     }
     catch( error){
       console.log(error);
     }
    }
    
    //run function checkIfWalletIsConnected when the page loads
    useEffect(()=> {
     checkIfWalletIsConnected();
    }, []);
    
    //connect to wallet
    const walletNotConnected = () => (
     <button onClick={connectWallet} className="connect-to-wallet-button">
       Connect to Wallet
     </button>
    );
    
    //wallet connected
    const walletConnected = () => (
     <div>
       <p>Connected to the wallet</p>
     </div>
    );
    
    return (
     <div className="App">
       <div style={{display: 'flex', justifyContent:'center', height: '50px'}}>
           {currentAccount === "" ? walletNotConnected()  : walletConnected()}
           <br />
       </div>
     </div>
    );
    };
    
    export default App;
    

    Now the following code will connect to the latest active network. So if the user was on the Ethereum Mainnet it will connect to Ethereum, if the user was on the Rinkeby Test Network it will connect to that. However, in many cases we need to the user to connect to a certain network.

  4. You can check to see which network the user is connected to and prompt the user with a message to change the network they are on. Modify connectWallet in App.js as below.

    const connectWallet = async () => {
      try {
        const {ethereum} = window;
    
        if(!ethereum) {
          alert("Opps, looks like there is no wallet!");
          return;
        }
    
        const currentNetwork = ethereum.networkVersion;
        console.log("Current network", currentNetwork);
    
        //check which network the wallet is connected on 
        if(currentNetwork != 4){
          // prompt user with a message to switch to network 4 which is the rinkeby network on metamask
          alert("Opps, only works on Rinkeby! Please change your //network :)");
          return;
        };
    
        const accounts = await ethereum.request({ method: "eth_requestAccounts"});
        setCurrentAccount(accounts[0]); 
    
      }
      catch( error){
        console.log(error);
      }
    }
    
  5. A better way to do this is to directly prompt the user with the request to switch the network. Instead of asking the user to change the network they are connected on. Change the if statement with the following lines.

         // request to switch the network 
         const tx = await ethereum.request({method: 'wallet_switchEthereumChain', params:[{chainId: 
    '0x4'}]}).catch()
          if (tx) {
            console.log(tx)
          }
    
  6. By default Chain 4 is already defined in Metamask. You can also prompt the user to add a new network which is not already defined. Here is how you can add the Avalanche network. Add the following piece of code just before requesting access to the account.

      // define avax network values 
      const avax_mainnet = [{
        chainId: '0xA86A',
        chainName: 'Avalanche Mainnet C-Chain',
        nativeCurrency: {
          name: 'Avalanche',
          symbol: 'AVAX',
          decimals: 18
        },
        rpcUrls: ['https://api.avax.network/ext/bc/C/rpc'],
        blockExplorerUrls: ['https://snowtrace.io/']
        }]

        // request to add the new network 
        const tx = await ethereum.request({method: 'wallet_addEthereumChain', params:avax_mainnet}).catch()
        if (tx) {
            console.log(tx)
        }

🎉 There you go; that's how you can use a crypto wallet in your app! The next step would be to connect to the smart contract and do some cool stuff such as mint you nft, swap tokens etc.


Overall, it's good to know some js and html to put together a well-tailored frontend for your application.

If you have any questions, do drop them below or reach out to me on Twitter!