How to make a React HOC for Ethereum Dapps in 42 lines of code
I lied.
It’s actually 54 lines.
You trusted me and I took advantage of you. I’m sorry.
But if you take out the import
/export
statements and some empty lines, it’s only 42 lines of code.
Please forgive me, I promise you this will be worth it!
What is this about?
Web3 is the bridge between the browser and the Ethereum blockchain. If you are making an Ethereum Dapp with React, your first challenge would be getting Web3 into your components.
A great library that helps with this is React-Web3, but this article is for those of you who prefer to know how to do something from “scratch” even if you may never need to.
If you just want to get started making an Ethereum Dapp, maybe you’d like my other article:
Make an HOC that will inject Web3
This is our goal.
We want to wrap a component with withWeb3
(a higher-order component) and get the Web3 object as a prop
in our component.
In other words, we want to use it like this:
Don’t worry about the JSON.stringify()
, it just prints out the Web3 object. The point is that MyComponent
has access to the web3
object.
The actual HOC
Don’t worry, I’ll walk you through it. But here it is first:
In short,withWeb3
is a function that:
- Takes in a component (that we call
PassedComponent
), - Tries to get the
web3
object from the browser, - Renders
<PassedComponent web3={web3} />
when it’s ready, - Or renders a loading message if
web3
is not ready yet.
Basically, it’s just trying to call getWeb3
, and when it’s done, it will set it to our component state so that we can render PassedComponent
with web3
as a prop.
So you’re probably wondering, what’s inside getWeb3.js
?
Actually getting the web3 object
Here’s where it gets a little tricky. Here is the code for grabbing web3
:
There are essentially two functions here, asking two different questions:
- Which Web3 to grab? — First (in
resolveWeb3
), we create a function where we actually attempt to grab theweb3
object. This requires deciding which Web3 to grab. - When to grab Web3? — Second (in our default
export
), we try to call the above function (resolveWeb3
) in two different instances.
We can talk about these two separately.
Which Web3 to grab?
In resolveWeb3
we are trying to figure out whether the user is running MetaMask or Mist, or if they are running a local testrpc
or truffle develop
server (the default ports for these are 8545
and 9545
respectively).
If web3
already exists inside the window
object, then we know MetaMask or Mist is running. Otherwise, we default to the local web3
.
Either way, we grab the web3
object and call the resolve
callback so we can send it back up to our app.
When to grab Web3?
For the second function, we return a Promise where we call resolveWeb3
in one of two cases:
- Upon the document
load
event (i.e. when the page is done loading). This is so that MetaMask has a chance to injectweb3
before we try to grab it. - Whenever the
getWeb3()
function is called.
The reason why we need the second case is because you might want to include Web3 only when the user navigates to a component/page that requires it.
If that is the case, then you cannot rely on the document load
event, since that would’ve happened a long time ago.
And that’s it!
Hopefully now you can implement your own HOC that brings in Web3 and whatever else you need, like a truffle-contract
instance, or the accounts
array. I do something like this in my boilerplate Truffle Box project:
You might want to read my other article if the above speaks to you.
I hope this was at least somewhat interesting to you, and if so, I’d love for you to hold down that clap button.