DEV Community

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

Posted on

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)