Building a Simple React Dapp on The Tezos Blockchain — Part 3

Chaim Lev-Ari
Tezos Israel
Published in
4 min readJul 15, 2020

NOTE: This is part 3 of a series of posts about how to connect a react webapp to the tezos blockchain. For other posts see:

  1. Part 1 — Bootstrapping
  2. Part 2 — Connect to a wallet
  3. Part 3 — Connect and interact with a contract

Complete code for this series is here.

Connect to Contract:

If you didn’t copy the contract address, go into contracts/build/contracts/Counter.json. You'll see something like this:

Copy the address value from this file, this is YOUR_CONTRACT_ADDRESS.

Now, let’s create another hook useContract that will connect us to the counter contract.

use-contract.js

Replace YOUR_CONTRACT_ADDRESS with the contract address you copied.

What we do here, is to use Taquito to load the contract at the provided address, and then load its storage. We load the storage in this hook and not in another hook because storage is dependent on the contract.

Let’s connect it to see how it works.

If you review the code (or even better, write it in your App.js file), you’ll see that we imported the contract hook and used it. The main difference from what we saw until now, is the connect function. Since connectToContract also needs to be called when connecting, we call them both in this function. The order is important because all the settings (network, etc.) are set in the connectToWallet. We might be able to call it in a different function, just to make the calls independent of each other.

Interact with the contract

We want the user to be able to increase and decrease the counter. The contract API lets its users increase and decrease any amount, but we will stick to 1.

Let’s implement the increase function first. We will implement it inside the App component, although in a new hook or inside the contract hook is also possible.

Bottom of App component (in App.js inside the App function)

And change the increase button to

Note that increase calls setOperationError and setOperationLoading, so let's add them in the upper part of the App component:

And of course, we want to show it in the app, so replace the buttons sections with this:

Note how we set the buttons to be disabled when the operation is loading because we don’t want the user to click a few times.

Let’s see it happening. Go to the browser and click increase (connect again if needed). Since it’s the first operation on the contract we need to reveal it on the chain, so you’ll be asked to permit to operations. Once you agree, a beacon popup will be open, you can close it and see how the app is loading and the buttons are greyed out (disabled). Once the operation is confirmed on-chain, they will be enabled again.

What’s wrong?

The counter didn’t change. If you refresh the page and reconnect, you’ll see that it did increase and the account balance is a bit lower then what it was.

Why didn’t it update automatically?

Because we didn’t tell it to. Let’s do that.

Auto-sync account balance and contract storage.

Ok, this is the tricky part, I’m pretty sure I’ve got a good solution, but if you think of something else, please let me know.

We want to update the balance and storage when an operation occurs. We can use useEffect for that.

For instance:

That’s just pseudocode, as storage is in the contract, and balance is in the account, we will implement them in the different hooks.

Let’s add a counter of the contract operations, this will be the variable through which we track that an operation has been done.

useContract:

What did we change?

We added the operations counter, and instead of loading the storage when the contract is loaded, we increased the operations counter. With that, we also added a useEffect that is dependent on the counter and contract and calls loadStorage whenever one of its dependencies change.

If you check your app now, it should act the same as before. The difference is that we expose increaseOperationsCount so we can call it inside increase after the confirmation. Let's do that. Add increaseOperationsCount(); after await op.confirmation();.

Try your app again, this time the counter should increase by one, but the balance didn’t. That’s because we need to implement the same inside useBalanceState. If you look at your useBalanceState you'll see that we already have the useEffect, we just need to add a dependency on operationsCount, that means passing it into the hook, and adding it to the dependencies array:

In App.js, we need to pass the operationsCount into useBalanceState, that means to move the call to this hook after the call to useContract (because operationsCount comes from useContract). Let's do that and see if it works.

The decrease function is almost the same as the increase, so I’ll leave it for you.

Wrap up

This was just a short (well, at least was supposed to be short) review of how to create a simple react app that interacts with Tezos.

Note: I ignored a lot of things here, like best practices, security, and more. I am still learning this stuff as I go.

A few things you can do:

  • While writing this I understood that the contract interactions should also be in the contract hook, feel free to refactor and move them there.
  • Implement decrease
  • Let the user decide the amount to increase/decrease
  • Connect automatically when the user opens the app
  • Check the repo to see the whole code.
  • There’s another contract that comes with truffle examples (actually two, but the migrations contract is used behind the scenes), implement interaction with it.
  • Write me some comments — here or on twitter to @chiptus
  • read Claude Barde’s post for more info about the implementation
  • Check Tezos Israel at tezos.co.il

--

--