DEV Community

Cover image for How to Build a dApp with React, Solidity, and MetaMask
Raji moshood
Raji moshood

Posted on

1

How to Build a dApp with React, Solidity, and MetaMask

Introduction

Decentralized applications (dApps) run on blockchain networks, enabling trustless, transparent, and censorship-resistant functionality. In this guide, we’ll build a dApp using React, Solidity, and MetaMask, integrating Web3.js and Ethers.js for blockchain interactions.

What You'll Learn:

✔ Writing smart contracts in Solidity
✔ Deploying contracts on Ethereum testnet
✔ Connecting a dApp to MetaMask using Web3.js & Ethers.js
✔ Executing blockchain transactions from React

  1. Setting Up the Development Environment

Prerequisites

Ensure you have the following installed:

Node.js (v16 or later)

MetaMask browser extension

Hardhat (Ethereum development environment)

Step 1: Initialize a Hardhat Project

mkdir my-dapp && cd my-dapp
npm init -y
npm install --save-dev hardhat
npx hardhat
Enter fullscreen mode Exit fullscreen mode

Select “Create a basic sample project” and install dependencies when prompted.

  1. Writing a Smart Contract in Solidity

Step 1: Create a Solidity Contract

Inside contracts/, create a file named MyContract.sol:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

contract MyContract {
    uint256 public counter;

    function increment() public {
        counter++;
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Compile the Contract

npx hardhat compile
Enter fullscreen mode Exit fullscreen mode

Step 3: Deploy the Contract

Modify scripts/deploy.js:

const hre = require("hardhat");

async function main() {
  const Contract = await hre.ethers.getContractFactory("MyContract");
  const contract = await Contract.deploy();
  await contract.deployed();
  console.log("Contract deployed to:", contract.address);
}

main().catch((error) => {
  console.error(error);
  process.exit(1);
});
Enter fullscreen mode Exit fullscreen mode

Run the deployment script:

npx hardhat run 
Enter fullscreen mode Exit fullscreen mode
scripts/deploy.js --network localhost
Enter fullscreen mode Exit fullscreen mode
  1. Connecting the dApp to MetaMask with Web3.js & Ethers.js

Step 1: Install Web3.js & Ethers.js

npm install web3 ethers
Enter fullscreen mode Exit fullscreen mode

Step 2: Connect React to MetaMask

In App.js, set up MetaMask connection:

import { useState } from "react";
import { ethers } from "ethers";

function App() {
  const [account, setAccount] = useState("");

  async function connectWallet() {
    if (window.ethereum) {
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const accounts = await provider.send("eth_requestAccounts", []);
      setAccount(accounts[0]);
    } else {
      alert("MetaMask not found");
    }
  }

  return (
    <div>
      <button onClick={connectWallet}>Connect Wallet</button>
      <p>Connected Account: {account}</p>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode
  1. Interacting with the Smart Contract

Step 1: Load the Contract in React

Create contractABI.js with ABI (after deployment, copy from artifacts/contracts/MyContract.json):

const contractABI = [
  {
    "inputs": [],
    "name": "increment",
    "outputs": [],
    "stateMutability": "nonpayable",
    "type": "function"
  },
  {
    "inputs": [],
    "name": "counter",
    "outputs": [{"internalType": "uint256", "name": "", "type": "uint256"}],
    "stateMutability": "view",
    "type": "function"
  }
];

export default contractABI;
Enter fullscreen mode Exit fullscreen mode

Step 2: Fetch Contract Data in React

Modify App.js:

import { useState, useEffect } from "react";
import { ethers } from "ethers";
import contractABI from "./contractABI";

const contractAddress = "YOUR_DEPLOYED_CONTRACT_ADDRESS";

function App() {
  const [account, setAccount] = useState("");
  const [contract, setContract] = useState(null);
  const [counter, setCounter] = useState(0);

  async function connectWallet() {
    if (window.ethereum) {
      const provider = new ethers.providers.Web3Provider(window.ethereum);
      const signer = provider.getSigner();
      const accounts = await provider.send("eth_requestAccounts", []);
      setAccount(accounts[0]);

      const contractInstance = new ethers.Contract(contractAddress, contractABI, signer);
      setContract(contractInstance);
      fetchCounter(contractInstance);
    } else {
      alert("MetaMask not found");
    }
  }

  async function fetchCounter(contractInstance) {
    const count = await contractInstance.counter();
    setCounter(count.toNumber());
  }

  async function incrementCounter() {
    if (contract) {
      const tx = await contract.increment();
      await tx.wait();
      fetchCounter(contract);
    }
  }

  useEffect(() => {
    if (contract) fetchCounter(contract);
  }, [contract]);

  return (
    <div>
      <button onClick={connectWallet}>Connect Wallet</button>
      <p>Connected Account: {account}</p>
      <p>Counter Value: {counter}</p>
      <button onClick={incrementCounter}>Increment Counter</button>
    </div>
  );
}
Enter fullscreen mode Exit fullscreen mode

export default App;

  1. Testing the dApp on a Testnet

Step 1: Get Testnet Funds

  1. Open MetaMask.

  2. Switch to Goerli or Sepolia Testnet.

  3. Get test ETH from a faucet (https://goerlifaucet.com).

Step 2: Deploy to Testnet

Modify hardhat.config.js:

module.exports = {
  solidity: "0.8.19",
  networks: {
    goerli: {
      url: "https://eth-goerli.alchemyapi.io/v2/YOUR_ALCHEMY_API_KEY",
      accounts: ["YOUR_PRIVATE_KEY"]
    }
  }
};
Enter fullscreen mode Exit fullscreen mode

Deploy:

npx hardhat run scripts/deploy.js --network goerli
Enter fullscreen mode Exit fullscreen mode
  1. Enhancing the dApp

✔ Use IPFS or Arweave for decentralized file storage.
✔ Add WalletConnect to support multiple wallets.
✔ Use Moralis API for indexing blockchain data.
✔ Deploy front-end on Vercel or Netlify for easy hosting.

Conclusion

In this guide, we built a React + Solidity dApp that connects to MetaMask, interacts with smart contracts, and runs transactions on Ethereum.

✔ Wrote and deployed a Solidity contract
✔ Connected React with MetaMask using Ethers.js
✔ Interacted with smart contracts from the front end

I am open to collaboration on projects and work. Let's transform ideas into digital reality.

Web3 #Ethereum #Solidity #React #MetaMask #dApps

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

AWS GenAI LIVE!

GenAI LIVE! is a dynamic live-streamed show exploring how AWS and our partners are helping organizations unlock real value with generative AI.

Tune in to the full event

DEV is partnering to bring live events to the community. Join us or dismiss this billboard if you're not interested. ❤️