How to trigger a contract read on button click in Scaffold-ETH 2

How to trigger a contract read on button click in Scaffold-ETH 2

ยท

3 min read

Scaffold-ETH 2 has emerged as an indispensable toolkit for developers venturing into the exciting world of decentralized application (DApp) development on the Ethereum blockchain. Its robust features and intuitive design streamline the process of building, testing, and deploying DApps, making it a go-to choice for both novice and experienced blockchain developers.

However, as you dive deeper into the realm of React-based DApp development with Scaffold-ETH 2, you may encounter a common yet perplexing challenge: how do you trigger a contract read or write operation in response to a user action, like a button click? This task might seem straightforward at first glance, but it introduces a nuanced complexity due to the nature of React hooks, which form the backbone of interaction with smart contracts in Scaffold-ETH 2.

Many developers stumble upon an error when attempting to directly invoke these hooks within event handlers, leading to the frustrating message: Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This blog post aims to demystify this hurdle and guide you through two effective strategies to seamlessly integrate contract interactions with user events, ensuring a smooth and responsive user experience in your DApp.

There are two approaches to trigger a contract read or write operation on a button click: using the refetch function from useScaffoldContractRead, or doing it imperatively with useScaffoldContract.

Let's break down these approaches:

Using refetch from useScaffoldContractRead

useScaffoldContractRead is a custom hook that wraps around wagmi's useContractRead, and it expose a refetch function. This function can be used to re-execute the contract read operation.

Here's how you can use refetch:

const { data: transactionHash, refetch } = useScaffoldContractRead({
    contractName: "MultiSigWallet",
    functionName: "getTransactionHash",
    args: [/* arguments here */],
});

const handleButtonClick = () => {
    refetch(); // Trigger the contract read operation
};

In this approach, the refetch function is called on button click, re-executing the contract read with the current arguments.

Imperative Read with useScaffoldContract

For cases where you need to read data with changing arguments upon each button click, you can use useScaffoldContract to get an instance of your contract and then call the contract's read methods imperatively.

Here's how it works:

const { data: yourContract } = useScaffoldContract({
  contractName: "MultiSigWallet",
});

const handleRead = async () => {
  const result = await yourContract?.read.getTransactionHash([/* arguments here */]);
  // Do something with the result
};

This example gets the contract instance using useScaffoldContract and then uses it to call the getTransactionHash method directly within an event handler function (like a button click handler).

Summary

  • Using refetch: Suitable for re-fetching data with the same arguments. The refetch function from useScaffoldContractRead can be called on a button click to re-run the read operation.

  • Imperative Read: When you need to pass different arguments on each read, use useScaffoldContract to get a contract instance and then call its read methods directly. This approach provides more flexibility in handling dynamic arguments.

Each method has its use cases depending on whether your read operation requires static or dynamic arguments, and whether you prefer a more declarative or imperative approach in your React component.

ย