useContractQuery
Read-only contract call, a ReviveApi dry-run cached like any query
useContractQuery performs a read-only contract call: a ReviveApi.call
dry-run that never signs or submits anything. data is the decoded return
value; pass the expected type as the generic
(useContractQuery<bigint>(…)). Results are cached under the contract
identity, the method name and the args, so several components reading the
same value share one dry-run; different args are different cache entries.
While the contract handle hasn't resolved the query stays disabled
(isPending), no need to guard on the handle. If the call reverts the query
errors with contract query "method" reverted and the revert value attached
as error.cause; an unknown method name errors with
contract has no method "method".
Reads are one shot, not subscriptions. Call refetch() (for example from a
transaction's onSuccess) to observe a new value after a write.
Usage
import { useContract, useContractQuery } from "@use-truapi/react";
import { COUNTER_LIBRARY, cdmJson } from "./counter-contract";
function Count() {
const contract = useContract(cdmJson, COUNTER_LIBRARY);
const count = useContractQuery<bigint>(contract.data, "getCount", []);
if (count.isPending) return <p>Reading count…</p>;
if (count.error) return <p>Read failed: {count.error.message}</p>;
return (
<p>
Count: {count.data.toString()}{" "}
<button type="button" onClick={() => count.refetch()}>Refresh</button>
</p>
);
}In React, pass the resolved handle, contract.data, as the first argument.
<script setup lang="ts">
import { useContract, useContractQuery } from "@use-truapi/vue";
import { COUNTER_LIBRARY, cdmJson } from "./counter-contract";
const contract = useContract(cdmJson, COUNTER_LIBRARY);
const count = useContractQuery<bigint>(contract, "getCount", []);
</script>
<template>
<p v-if="count.isPending">Reading count…</p>
<p v-else-if="count.error">Read failed: {{ count.error.message }}</p>
<p v-else>
Count: {{ count.data?.toString() }}
<button type="button" @click="count.refetch()">Refresh</button>
</p>
</template>In Vue, pass the whole query result returned by useContract or
useContractAt; the read unwraps contract.data reactively and enables
itself once the handle resolves. Args may be a getter (() => [props.id]) so
reactive args re-run the read.
Gate the read with enabled while an input is incomplete; it combines with
the built-in "contract resolved" gate:
const balance = useContractQuery<bigint>(contract.data, "balanceOf", [owner], {
enabled: owner !== undefined, // Vue: () => owner.value !== undefined
});See also
useContractanduseContractAtobtain the handle to read from.useContractTxis the write-side counterpart; refetch after it succeeds.
API reference
React
function useContractQuery<T>(
contract,
method,
args,
options?): UseQueryResult<T, Error>;Read-only contract call (ReviveApi.call dry-run) — cached under the
contract identity, method and args.
const count = useContractQuery(contract, "getCount", []);Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type |
|---|---|
contract | | Contract<ContractDef> | undefined |
method | string |
args | readonly unknown[] |
options? | { enabled?: boolean; query?: QueryOptions<T>; } |
options.enabled? | boolean |
options.query? | QueryOptions<T> |
Returns
UseQueryResult<T, Error>
Vue
function useContractQuery<T>(
contract,
method,
args?,
options?): QueryResult<T>;Read-only contract call (ReviveApi.call dry-run) — cached under the
contract identity, method and args; reactive args re-run it.
Type Parameters
| Type Parameter | Default type |
|---|---|
T | unknown |
Parameters
| Parameter | Type | Default value |
|---|---|---|
contract | QueryResult<Contract<ContractDef>> | undefined |
method | string | undefined |
args | MaybeGetter<readonly unknown[]> | [] |
options? | { enabled?: MaybeGetter<boolean>; query?: QueryOptions<T>; } | undefined |
options.enabled? | MaybeGetter<boolean> | undefined |
options.query? | QueryOptions<T> | undefined |
Returns
QueryResult<T>