Ethereum: Creating a Block Explorer with React (Part 1)

Create a basic React app

This is the first article in a mini-series that will step through building a simple Ethereum block explorer using React and web3. This first article covers creating and configuring the basic React app ‘skeleton’, while later articles will build out the functionality. React is a JavaScript library for building user interfaces created by the folk at Facebook. Read more about it here: https://facebook.github.io/react/.

These steps we documented against Ubuntu 16.04 LTS.

Note: I am not an expert in React, in fact I’ve barely dabbled with it. The goal of this article is to demonstrate React and web3. There is a heap of articles out there about React and React-Router, some useful, others not so much. This article documents my efforts to learn React while exploring the capabilities of Ethereum, the web3 library, and geth. Hopefully this won’t become another ‘not so useful’ article.

Previously…

Check out these previous articles which describe setting up the dev environment and other prerequisites:

Create a new React App

First we need to install create-react-app. Refer https://github.com/facebookincubator/create-react-apps

sudo npm install -g create-react-app

Next, create a new React app (this step may take a few minutes to complete.)

create-react-app blockexp

Output:

...
We suggest that you begin by typing:
	cd blockexp
	npm start
Happy hacking!

This will create a new directory blockexp. As the message suggests, we’ll change into the directory and start the the development server:

cd blockexp
npm start

This should automatically launch Firefox at http://localhost:3000/ and display the default app:

create-react-app default

Stop the server from the terminal by typing Ctrl + C, and Firefox should close automatically.

Setup application structure

Now that the basic app is working, we need to reorganise a few things. By default we get a project folder like this:

default directory structure

index.html is the main entry point of our app, and index.js is the main loader.

The node_modules subdirectory has a heap of stuff in it, but we don’t need to worry about it for this exercise so I’ve omitted it for simplicity.

Change directory into src:

cd src

The boilerplate app has a single component named App.js. We’ll be creating our own components, so this can be removed:

rm App.js

Now create some new subdirectories to store our components. The first component will be called App:

mkdir components
mkdir components/App

We’ll reuse the default logo.svg and App.css, so move them from the top directory src/ into the src/components/App subdirectory. We’ll also rename App.css to style.css:

mv logo.svg components/App/logo.svg
mv App.css components/App/style.css

Change into the App directory:

cd components/App

Create an empty index.js file:

touch index.js

Create two more subdirectories Home and Block, each with empty index.js and style.css files:

cd ..
mkdir Home
touch Home/index.js
touch Home/style.css
cp -r Home/ Block/

The resulting layout should look like this:

default directory structure

At this stage if we were to start the server with npm start again, we’d get an error because App.js no longer exists. To resolve this we need to fix the imports in /src/index.js.

Edit /src/index.js and locate this line near the top:

import App from './App';

Update the path to reflect the new directory structure:

import App from './components/App';

Install dependencies

This React app will be a single-page app using react-router-dom for navigation. This is a great reference for getting started with react-router: https://reacttraining.com/react-router/web/guides/quick-start.

We’ll also need web3 to interact with the blockchain. Read more about it here: https://github.com/ethereum/wiki/wiki/JavaScript-API

Make sure you are in the project top directory blockexp/ and type:

sudo npm install --save react-router-dom
sudo npm install --save web3

The --save parameter will update the dependencies in package.json of the React app. We can review it quickly by typing cat package.json. The relevant section should look like this:

...
"dependencies": {
	"react": "^15.4.2",
	"react-dom": "^15.4.2",
	"react-router-dom": "^4.0.0",
	"web3": "^0.18.2"
},
...

Now run npm start to make sure there are no errors. If all has worked a blank page should load at http://localhost:3000/.

Create the page template

Now we will create a page that will display the various components.

Leave the server running and edit the file /src/components/App/index.js. We’ll re-use the code from the original App.js, with a few small changes. Enter the following:

import React, { Component } from 'react';
import logo from './logo.svg';
import './style.css';

class App extends Component {
  render() {
    return (
      <div className="App">
        <div className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <h2>Block Explorer</h2>
        </div>
        <div className="App-nav">
          {/* Place holder */}
        </div>
      </div>
    );
  }
}
export default App;

When the file is saved, http://localhost:3000/ should automatically refresh:

create-react-app default

Stop the server again from the terminal using Ctrl + c.

React Router and Navigation

Next we’ll setup the navigation routing for the simple block explorer. The site will support two URL paths:

  • / - The root or home page . We’ll use this page to list recent blocks
  • block/[hash] - The block info page. We’ll use these pages to show details of individual blocks

Defining routes

Go back to the file /src/components/App/index.js and add some additional imports after import './style.css';:

import Block from './../Block';
import Home from './../Home';
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'

Next, locate this section:

<div className="App-nav">
  {/* Place holder */}
</div>

Replace {/* Place holder */ with:

<Router>
  <div>
    <Link to="/">Home</Link>
    <Link to="/block">Block</Link>
    <Route exact path="/" component={Home}/>
    <Route exact path="/block" render={() => (
      <h3>Please select a blockHash.</h3>
    )}/>
    <Route path="/block/:blockHash" component={Block}/>
  </div>
</Router>

I’ll try to give some explanation here. First, we are using Link to render a clickable link to / that will be displayed on the page, and another that navigates to /block. We could add more links if needed, but this is fine for now.

Next, we are defining some routing rules. When the browser path matches the path parameter, the {Home} component will be rendered. Simlarily, we map the exact path /block to a function which renders a message Please select a blockHash.

Finally, we map path /block/:blockHash to the {Block} component. This is an example of a URL parameter, and we’ll use it to display the relevant block details. Read more about URL Params here: https://github.com/reactjs/react-router-tutorial/tree/master/lessons/06-params

Create the Home component

Now we need to create the Home component. Edit /src/components/Home/index.js and enter the following:

import React, { Component } from 'react';
import './style.css';

class Home extends Component {

    render() {
        return (
            <div className="Home">
                <h2>Home page</h2>
            </div>
        );
    }
}

export default Home;

This component simply renders a div with the heading Home page.

Create the Block component

Edit /src/components/Block/index.js and enter the following:

import React, { Component } from 'react';
import './style.css';

class Block extends Component {
  render() {
    return (
      <div className="Block">
        <h2>Block Info</h2>
      </div>
    );
  }
}
export default Block;

Putting it all togethor

Run npm start from the top project directory blockexp/. Firefox should open and display the page like this:

create-react-app default

Clicking the Home link should refresh the page. We can also click the Block link which will return the message Please select a blockHash:

create-react-app default

Wrapping up

That’s it for this article. Stay tuned for the next article where the app is expanded to list recent blocks from a local private blockchain using web3.