May 31, 2025
Web Development, Web3
DApp, Ethereum, MetaMask, Web3, WebDev

Integrating MetaMask with your React application is essential for building decentralized applications (dApps) on Ethereum or any EVM-compatible blockchain. In this guide, we’ll walk through:
ethers.jsBefore we start, make sure you have:
npx create-react-app my-dapp)ethers.js library installed:npm install ethers
MetaMask injects an ethereum object into the browser’s window. To check if MetaMask is installed:
if (typeof window.ethereum !== 'undefined') {
console.log('MetaMask is installed!');
}
Create a button that connects to MetaMask and retrieves the current user’s address:
import React, { useState } from 'react';
const ConnectWallet = () => {
const [account, setAccount] = useState(null);
const connectWallet = async () => {
if (typeof window.ethereum === 'undefined') {
alert('Please install MetaMask!');
return;
}
try {
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
setAccount(accounts[0]);
} catch (error) {
console.error('Connection error:', error);
}
};
return (
<div>
<button onClick={connectWallet}>
{account ? `Connected: ${account}` : 'Connect MetaMask'}
</button>
</div>
);
};
export default ConnectWallet;
Now let’s add the ability to send a small ETH transaction. We’ll use ethers.js for convenience and reliability.
ethers.js and setup provider + signer:import { ethers } from 'ethers';
const sendTransaction = async () => {
if (!window.ethereum) {
alert('MetaMask is not available');
return;
}
try {
// Connect to provider and get signer
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const recipient = '0xAbC123...DEF456'; // Replace with actual address
const tx = {
to: recipient,
value: ethers.utils.parseEther('0.01'), // sending 0.01 ETH
};
const txResponse = await signer.sendTransaction(tx);
console.log('Transaction sent:', txResponse.hash);
const receipt = await txResponse.wait();
console.log('Transaction confirmed:', receipt);
} catch (error) {
console.error('Transaction failed:', error);
}
};
<button onClick={sendTransaction}>Send 0.01 ETH</button>
Instead of sending ETH, you can ask the user to sign a message:
const signMessage = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const signature = await signer.signMessage("Sign this to prove you own the wallet.");
console.log("Signature:", signature);
};
to addresses before sending ETH.window.ethereum.on('accountsChanged') to detect wallet changes.With just a few lines of code, your React app can:
ethers.jsThis is a core part of any dApp UX. Once this is in place, you can extend functionality to include ERC-20 token transfers, smart contract interactions, and wallet authentication.
import React, { useState } from 'react';
import { ethers } from 'ethers';
const WalletConnector = () => {
const [account, setAccount] = useState(null);
const connectWallet = async () => {
if (!window.ethereum) {
alert('Please install MetaMask');
return;
}
const accounts = await window.ethereum.request({ method: 'eth_requestAccounts' });
setAccount(accounts[0]);
};
const sendTransaction = async () => {
const provider = new ethers.providers.Web3Provider(window.ethereum);
const signer = provider.getSigner();
const tx = {
to: '0xAbC123...DEF456', // replace with valid address
value: ethers.utils.parseEther('0.01'),
};
const txResponse = await signer.sendTransaction(tx);
console.log('Sent:', txResponse.hash);
await txResponse.wait();
console.log('Confirmed');
};
return (
<div>
<button onClick={connectWallet}>
{account ? `Connected: ${account}` : 'Connect MetaMask'}
</button>
{account && (
<button onClick={sendTransaction}>Send 0.01 ETH</button>
)}
</div>
);
};
export default WalletConnector;