Ikeh Akinyemi Ikeh Akinyemi is a Software Engineer based in Rivers State Nigeria. He’s passionate about learning pure and applied mathematics concepts, open source, and software engineering.

Using Drizzle and React to write DApp frontends

6 min read 1889

Laptop, Tablet, and Mobile Device Showing the Same Content

Frameworks have made it easier and faster to bootstrap and configure web projects by providing the initial code/setup and tools needed to start building any frontend application. The world of blockchain and DApp development is no exception.

In this tutorial, we’ll show you how to use the Drizzle framework to build frontend applications on Ethereum. We’ll examine a practical example in which we’ll use Drizzle alongside React to build a DApp.

Here’s what we’ll cover:

To comfortably understand the concepts we’ll cover in this tutorial, you’ll need basic knowledge of the following:

What is Drizzle?

Drizzle as a framework based on the Truffle Suite. It’s a JavaScript library that provides interfaces for Web3, account and contract instantiation, and additional contract functionality and helps with wiring up the necessary synchronizations.

Drizzle is the main library. It contains the core logic of Drizzle and integrates manually with your application.

Drizzle can be installed as an npm package, meaning you’d need Node.js installed on your local machine to use the Node.js commands through the terminal to install Drizzle.

Alternatively, you can use Truffle Boxes to handle the installation.

Drizzle modules

Drizzle, the core library, offers a reactive store for frontend applications in Web3 and smart contracts. The reactive store is fashioned in likeness to Redux store, meaning it automatically updates when it detects updates on the state of the smart contract or that of the UI. We can incorporate Drizzle into any JavaScript-based project

There are two main modules that can be installed alongside Drizzle. These modules provide interfaces that make building DApps easier.

We made a custom demo for .
No really. Click here to check it out.

  • Drizzle-react helps you to easily bootstrap a React application with Drizzle. It provides a DrizzleProvider component and drizzleConnect helper method to make it easier to connect Drizzle with your React app. These are higher-order Provider components that help wrap the other components within our application and pass the state of Drizzle down to them
  • Drizzle React Components provides useful React components that are peculiar for common DApp functions. DApp functions such as ContractData, ContractForm, and LoadingContainer help to connect our account, easily read data from smart contracts, and write data to the blockchain

In the next section, we’ll build a DApp leveraging the two aforementioned modules together with the Drizzle core library within a React application.

How Drizzle integrates with React

Within our Drizzle application, we connect to the Ethereum blockchain using a Web3 provider. Then, using a configuration file, we configure the application to interact with the smart contract we intend for it to connect to.

Drizzle sets up and manages an internal state that stores the data returned from functions or expressions within the smart contract. Drizzle manages this state and keeps it up to date. Then, through React and drizzle-react, we update/rerender the UI on state changes, keeping the UI in sync with the smart contract’s state.

Drizzle uses the concept of the React’s Context API to implement passing of data down through the component tree of the whole application. This way, the context of our application is made available to every working part of our application.

With Drizzle, we can set up and integrate smart contracts that were wrote on the local development environment (local machine) into our frontend or import any smart contract through its public address and JSON interface into our frontend. Running the compile, and migrate Truffle-based commands during local development builds and deploys the smart contracts, then provides us with the build/contracts folder that contains the JSON interfaces to consume.

For this tutorial, we’ll focus on building the frontend of a DApp and how to integrate it with a smart contract or an existing smart contract on Etherscan.io.

How to build a frontend DApp using Drizzle and React

Now let’s set up our local development environment by bootstrapping our project from scratch using the Truffle framework. We’ll install and use the Truffle box alongside the ganache-cli tool, which enables us to set up a local blockchain without the hassle of running our own actual Ethereum node.

Run the following commands on the terminal to install the necessary tools mentioned above. Then, create a folder named drizzle-dapp, change directory into it, and initialize a frontend DApp.

npm install -g truffle
npm install -g ganache-cli
mkdir drizzle-react-tutorial
truffle unbox drizzle
ganache-cli -b 3

The command truffle unbox drizzle creates a full codebase that contains all the boilerplate code needed to build our project. We’ll focus on the /app folder because this is where the frontend will be located.

Boilerplate Codebase

The above command also installs ganache-cli globally on our local machine. The ganache-cli -b 3 command sets a mimic of a realistic blockchain to establish a DApp account integration between our frontend and smart contract.

Initialize Drizzle and DrizzleStore in React

Next, let’s import and initialize Drizzle for our DApp in the /app/src/index.js file:

import { Drizzle, generateStore } from "drizzle";
import { DrizzleContext } from "drizzle-react";

import SimpleStorage from "./../build/contracts/SimpleStorage.json";

const options = { contracts: [SimpleStorage] };
const drizzleStore = generateStore(options);
const drizzle = new Drizzle(options, drizzleStore);

ReactDOM.render(
  <DrizzleContext.Provider drizzle={drizzle}>
      <App />
  </DrizzleContext.Provider>,
document.getElementById("root"));

In the above code, we imported the functionalities exposed on drizzle and drizzle-react and imported sample contracts made available from the starter code provided by the truffle unbox drizzle command.

Also, with the above code, we initialized a store, drizzleStore, and a drizzle object.

Next, let’s edit and update the /app/src/App.js file:

import { DrizzleContext } from "@drizzle/react-plugin";
import { Drizzle } from "@drizzle/store";
import drizzleOptions from "./drizzleOptions";
import MyComponent from "./MyComponent";
import "./App.css";

const drizzle = new Drizzle(drizzleOptions);
const App = () => {
  return (
    <DrizzleContext.Provider drizzle={drizzle}>
      <DrizzleContext.Consumer>
        {drizzleContext => {
          const { drizzle, drizzleState, initialized } = drizzleContext;
          if (!initialized) {
            return "Loading..."
          }
          return (
            <MyComponent drizzle={drizzle} drizzleState={drizzleState} />
          )
        }}
      </DrizzleContext.Consumer>
    </DrizzleContext.Provider>
  );
}
export default App;

From the above code, the Drizzle Context Provider provides an extra object alongside the previous ones, an initialised state. This tells us when drizzle is initialized and connected to a web3 provider.

Once the state, initialised, is available or fully connected, we then pass it down to the our custom component, MyComponent.

Consuming DrizzleContext in other components

Now, let’s open the /app/src/MyComponent.js file where the MyComponent component is located. This is where we’ll consume all the props provided and passed through the DrizzleContext object.

import { newContextComponents } from "@drizzle/react-components";
...
const { AccountData, ContractData, ContractForm } = newContextComponents;

export default ({ drizzle, drizzleState }) => {
  return (
    <div className="App">
      <div className="section">
        <h2>Active Account</h2>
        <AccountData
          drizzle={drizzle}
          drizzleState={drizzleState}
          accountIndex={0}
          units="ether"
          precision={3}
        />
      </div>
      <div className="section">
        <h2>SimpleStorage</h2>
        <p>
          This shows a simple ContractData component with no arguments, along with a form to set its value.
        </p>
        <p>
          <strong>Stored Value: </strong>
          <ContractData
            drizzle={drizzle}
            drizzleState={drizzleState}
            contract="SimpleStorage"
            method="storedData"
          />
        </p>
        <ContractForm drizzle={drizzle} contract="SimpleStorage" method="set" />
      </div>
    </div>  
  )
}

In the above code, we’re simply integrating the account of the DApp with Drizzle to manage the account data. This also applies to the ContractData object. As the name suggests, this is an interaction of data between Drizzle and the sample contract, SimpleStorage.sol.

CacheCall and CacheSend Functions

Now that we’ve set up Drizzle on the frontend, let’s make calls to the smart contract using the cacheCall and the cacheSend functions made available as interfaces on drizzle. The functions also has access to the drizzleStore to store response from the smart contract within the store.

Next, let’s define a function to send contract data and store the response in the DApp’s state.

...
export default ({ drizzle, drizzleState }) => {
  ...
  const fetchData = () => {
    const state = drizzle.store.getState();
    const key = drizzle.contracts.SimpleStorage.methods.storedData.cacheCall();

    return state.contracts.SimpleStorage.methods.storedData[key].value;
  }
  ....
}
...

The above code snippet simply calls the smart contract, SimpleStorage, using the the cacheCall method. This call returns response data that would be stored in the drizzleStore and a key for accessing this data from the drizzleStore.

Then, using the key on the drizzleStore, the above function returns the value made available by the smart contract when it was called to the UI. This way, we can easily call our smart contracts and synchronize the response with the UI.

Next let’s define another function to send a transaction and store the response in our store:

...
export default ({ drizzle, drizzleState }) => {
  ...
  cnnst state = drizzle.store.getState();
  const id = drizzle.contracts.SimpleStorage.methods.set.cacheSend(
    3,
    { from: Addresse }
  );

  if (state.transactionStack[id]) {
    const transactionHash = state.transactionStack[id];
    return state.transactions[transactionHash].status;
  }
  ...
}
...

The above code snippet retrieves the state of the application, then initialize a transaction while providing it with the gas and from options. The from represents the address making the transaction. Calling the cacheSend method returns an id, and this id is used to access the state of the transaction on the DApp’s state.

Now we have connected the frontend of our DApp to the smart contract. On the terminal, run the following code to compile and migrate the smart contract:

truffle compile # compiles all the smart contract within the /contracts folder
truffle migrate # deploys the smart contract on the ganache-cli blockchain

Now we have our smart contracts and the frontend of the application ready. We should be able to type a value into the input field and make a transaction, and then the state of our smart contract will immediately update as well as the UI, automatically. The ContractForm component provides us with this input and form to interact with the smart contract.

Conclusion

In this tutorial, we introduced Drizzle as a framework of the Truffle suite, which makes it easy to sync our DApp together with the state of our smart contracts. Then, we explored the three methods through which Drizzle can be installed and used within a DApp. We also covered how to set up Drizzzle Context within our application.

Drizzle helps reduce the amount of boilerplate that is needed to bootstrap a DApp project. For next steps, we can extend our DApp to build anything, from a game to a shopping list or a blog platform, all on the blockchain platform.

You can extend the code used within this tutorial by building more components to make calls or send transactions for the features you want to incorporate within your DApp. Then, extend the smart contract to handle these features. The code used within this tutorial is available on GitHub.

Full visibility into production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, try LogRocket.

LogRocket is like a DVR for web apps, recording literally everything that happens on your React app. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app's performance, reporting with metrics like client CPU load, client memory usage, and more.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — .

Ikeh Akinyemi Ikeh Akinyemi is a Software Engineer based in Rivers State Nigeria. He’s passionate about learning pure and applied mathematics concepts, open source, and software engineering.

Leave a Reply