How to make a React HOC for Ethereum Dapps in 42 lines of code

React HOCs and Ethereum can play together nicely

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:

A usage example; This is what we are trying to achieve.

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:

Note that we are using async/await syntax.

In short,withWeb3 is a function that:

  1. Takes in a component (that we call PassedComponent),
  2. Tries to get the web3 object from the browser,
  3. Renders <PassedComponent web3={web3} /> when it’s ready,
  4. 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:

  1. Which Web3 to grab? — First (in resolveWeb3), we create a function where we actually attempt to grab the web3 object. This requires deciding which Web3 to grab.
  2. 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:

  1. Upon the document load event (i.e. when the page is done loading). This is so that MetaMask has a chance to inject web3 before we try to grab it.
  2. 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.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.