• React
  • Prepare Hooks

Prepare Hooks

In previous versions of wagmi, "transactional" hooks such as useSendTransaction and useContractWrite performed potentially long-running asynchronous work. On a slow network, these asynchronous tasks can take a while.

Performing asynchronous tasks in an event handler (like a button) or in an event that wasn't initiated by the user (like a page load) is not ideal as it can lead to a variety of connected user-experience (UX) related pitfalls (listed below).

Prepare Hooks allow you to eagerly perform this asynchronous work beforehand & generate the parameters required for their paired hook (e.g. usePrepareSendTransaction prepares a request for useSendTransaction).

wagmi currently has the following Prepare Hooks:

UX Pitfalls without Prepare Hooks

You may have noticed one of the following pitfalls when using "transactional" hooks without performing the asynchronous work beforehand.

Slow TTOW (Time To Open Wallet)

Performing long-running async work in between a user interaction (i.e. click handler) and opening the wallet can lead to a slow TTOW (Time To Open Wallet).

Under slow network conditions, it may confuse the end-user as to why the wallet is taking a while to open.

The video below shows the difference between a slow TTOW and a fast TTOW.

No upfront validation

When using "transactional" hooks such as useContractWrite & useSendTransaction, the user will only get feedback on the status of the transaction once they have invoked the click handler.

There are some cases where we can perform upfront validation on a contract or transaction request before the user interacts with the click handler (such as checking if we can still mint on a contract).

See the comparison below for when a user tries to mint a sold out NFT.

Validating after interactionValidating before interaction

By using a Prepare Hook, we can perform this eager validation before the click handler is invoked.

import * as React from 'react'
import { usePrepareContractWrite, useContractWrite } from 'wagmi'
export function MintNFT() {
  const { config, error, isError } = usePrepareContractWrite({
    address: '0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2',
    abi: [
        name: 'mint',
        type: 'function',
        stateMutability: 'nonpayable',
        inputs: [],
        outputs: [],
    functionName: 'mint',
  const { data, write } = useContractWrite(config)
  return (
      <button disabled={!write} onClick={() => write()}>
      {isError && <div>Error: {error.message}</div>}