What is Web3-React and How to use it for your dApp front-end?
Develop dApp frontends faster with Web3-React.
Are you building a dApp? If yes, then you must need to connect your dApp to a wallet. Web3-react might just be the tool you are looking for!
Web3-react is a web3 framework made by Noah Zinsmeister to help blockchain developers make modern Ethereum dApps using React hooks.
Let's explore web3-react! ๐โ
What is Web3-react?
Web3-react is a React-based framework that helps to ease the frontend development for your dApp.
Web3-react also acts as a state machine that maintains the data relevant to your dApp and injects it wherever needed in the component tree. Web3-React supports a wide range of wallets, from browser wallets like Metamask and Coinbase to hardware wallets like Trezor and Ledger.
In LearnWeb3, we use Web3-Modal for wallet connection in dApps. Web3-Modal is great for beginners, but as we scale our projects, handling Web3-Modal gets harder.
Thus web3-react can be a better option because:
- It's better for building modern dApps
- Has a better developer experience
- Reduces code redundancy
- And is an intuitive framework to work with
Why using Web3-react might be a better idea?
Web3-React provides flexibility in many ways. It has great support for many wallets as discussed earlier.
But even if the wallet is not included in web3-react packages, you can create your custom connectors and connect wallets other than those listed with web3-react!
Web3-react uses Ethers.js or Web3.js under the hood thus providing a smooth experience as connecting wallet using only ether.js can be a really painful process.
Note: Before moving forward, make sure you understand ContextAPI in other words, useContext hook. It is the key feature of Web3-React.
Installing web3-react
Let's install web3-react!
In this article, we assume that you have your ReactJS/NextJS app already set up.
In your app directory, run the following command to install web-react:
COPY
npm install @web-react/core
or
COPY
yarn add @web3-react/core
Now, for connecting browser-based wallets, we need to install the following web3-react package:
COPY
npm install @web3-react/injected-connector
or
COPY
yarn add @web3-react/injected-connector
And.. you have all the ingredients required to connect your dApp to a browser wallet! Let's start writing code to connect the wallet!
Connecting Wallet
This section assumes you have already created the app and installed the previous dependencies. Now that it's taken care of, let's get straight into this!
Step 1: Setting up Web3ReactProvider
Let's jump into your _app.js
(for Next) file under the pages
folder!
Edit the code such that it looks like this ๐โ
COPY
import '../styles/globals.css'
import { Web3ReactProvider } from '@web3-react/core'
import { providers, Web3Provider } from 'ethers'
function getLibrary(provider, connector) {
return new providers.Web3Provider(provider)
}
function MyApp({ Component, pageProps }) {
return(
<Web3ReactProvider getLibrary={getLibrary}>
<Component {...pageProps} />
</Web3ReactProvider>
)
}
export default MyApp
Done? Now let's understand the code!
This function is returning the provider object.
COPY
function getLibrary(provider, connector) { return new providers.Web3Provider(provider) }
The Web3ReactProvider is the Context Provider which passes all the data down the component tree.
COPY
function MyApp({ Component, pageProps }) { return ( <Web3ReactProvider getLibrary={getLibrary}> <Component {...pageProps} /> </Web3ReactProvider> ) }
Step 2: Setting up the Hooks
Now let's jump into your index.js
in the pages
folder.
COPY
import Head from 'next/head'
import Image from 'next/image'
import styles from '../styles/Home.module.css'
import { InjectedConnector } from '@web3-react/injected-connector'
import { useWeb3React } from '@web3-react/core'
import { useState } from 'react'
import { CONTRACT_ADDRESS, CONTRACT_ABI } from '../constants'
export default function Home() {
const [ result, setResult ] = useState("")
// web3-react hook, helps in fetching
// the data passed by Web3ReactProvider
const { active, activate, deactivate, account, library, connector, error } = useWeb3React()
// injected provider identifier
const injected = new InjectedConnector(
{
supportedChainIds:[80001]
}
)
const connectWallet = async () => {
try {
await activate(injected)
} catch (err) {
console.error(err)
}
}
const disconnectWallet = async () => {
try {
deactivate(injected)
} catch (err) {
console.error(err)
}
}
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<button onClick={connectWallet}>Connect Wallet</button>
{active? <span>Connected with <b>{account}</b></span>: <span>Not Connected</span>}
<button onClick={disconnectWallet}>Disconnect Wallet</button>
</div>
)
}
Okay, so now let's look at useWeb3React hook
COPY
const { active, activate, deactivate, account, library, connector, error } = useWeb3React()
useWeb3React
is a custom hook from the web-react library that returns a lot of useful functionalities.This hook returns:
COPY
connector; // connector object returns some useful connection // methods like activate() and deactivate() library; // library is the provider object that we // passed with the Web3ReactProvider chainId; // returns the chainId for the account that // is connected to the dApp account; // the account address of the connected account active; // active is a state variable which returns boolean values // that determines whether the wallet connection is // active or inactive error; // returns any error happening with the wallet connection
Now let's look at the injected variable -
COPY
const injected = new InjectedConnector({
supportedChainIds:[80001]
})
// we can list multiple networks by listing their
// chainIds, separated by comma
- Injected Connector is a class that takes input for the supported chainIds and returns a set of methods to interact with browser wallets.
- It will return an
UnsupportedChainId
error if the wallet is not connected to the right network. This error can be accessed from theerror
object returned by theuseWeb3React
hook.
As for the activate(injected)
and deactivate(injected)
, they are methods that will connect or disconnect the injected provider (browser wallet).
And BOOM๐ฅ you have a wallet connection setup ready!
Reading and Writing in the Contract
Now that we have connected our wallets, all that is left is the way to read from and write to the blockchain!
How do we achieve that?
We will be using the web3-react library
(provider) object to read/write from/on the blockchain
So, we are going to use the Mood dApp Contract that was built in LearnWeb3DAO's Freshman Track. Click here to get the smart contract.
Before we go deeper into this, make sure you have made an index.js
in the constants
folder(in the root directory), and it should have the following code -
COPY
// put your contract address in place of this gibberish
export const CONTRACT_ADDRESS = "0xabcabcabcabcabcabc";
// put your abi in this variable, it will be of the form [{},{}]
export const CONTRACT_ABI = [...]
Reading
For reading from smart contracts, we need two things-
- Contract Instance
- Provider
So let's write a function for reading from the smart contract!
COPY
const getMood = async () => {
const provider = library;
const contract = new Contract(
CONRTACT_ADDRESS,
CONTRACT_ABI,
provider
);
const tx = await contract.getMood();
tx.wait();
setResult(tx);
}
- We are setting the
provider
variable tolibrary
. Remember,library
was returned from theuseWeb3React
hook and it is a provider object. Handy, isn't it? - Then, we create a new Contract instance, this enables us to interact with the contract.
- Now it's time to create a transaction! We are calling the getMood() function from the contract here.
tx.wait()
waits for the transaction to complete.setResult(tx)
sets the value of the state variableresult
totx
's value.
Writing
For writing through the smart contracts, we need two things-
- Contract Instance
- Signer (to sign the transaction)
Let's create a writing function!
COPY
const setMood = async ( mood ) => {
const signer = await library.getSigner()
const contract = new Contract(
CONRTACT_ADDRESS,
CONTRACT_ABI,
signer
)
const tx = await contract.setMood(mood)
tx.wait()
alert("Mood set!")
}
The things have changed now, let's explore each of them step by step -
library
is a provider object, but we needed a signer, right? Well, a provider object has a method calledgetSigner()
that returns the signer object attached to this provider!- The
contract
is a Contract instance, but here, instead of passing the provider, we are passing a signer, because, for writing transactions, we need a signer to sign the transaction. - At last, we have now passed an argument to the contract function, because, the function from the contract takes an argument for setting a mood.
LFG!! You have made a dApp frontend with web3-react! It can read, and write on the blockchain too!๐ชโ
Conclusion
Web3-react is a very handy framework for building the dApp frontend in React/NextJS.
It is a very easy-to-use tool, but it can be confusing for beginners. For using this tool, you may need some knowledge of Context API.
Note: The Web3-React is not well documented, and the main branch of their repo does not even have docs. For reading their docs, shift to their v6
branch.
That's it for this blog!
See you around next time. ๐