Skip to content

useActorQuery

useActorQuery is a React hook for fetching data from Internet Computer canisters. It wraps TanStack Query’s useQuery with canister-specific functionality.

import { createActorHooks } from "@ic-reactor/react"
const { useActorQuery } = createActorHooks(backend)
function UserProfile({ userId }: { userId: string }) {
const { data, isPending, error } = useActorQuery({
functionName: "getUser",
args: [userId],
})
if (isPending) return <div>Loading...</div>
if (error) return <div>Error: {error.message}</div>
return <div>{data?.name}</div>
}
OptionTypeDescription
functionNamestringThe canister method to call
OptionTypeDefaultDescription
argsarray[]Arguments to pass to the method
enabledbooleantrueWhether the query should run
staleTimenumber0Time in ms before data is considered stale
gcTimenumber300000Time in ms before unused data is garbage collected
refetchIntervalnumber | falsefalsePolling interval in ms
refetchOnWindowFocusbooleantrueRefetch when window regains focus
refetchOnMountbooleantrueRefetch when component mounts
refetchOnReconnectbooleantrueRefetch when network reconnects
retrynumber | boolean3Number of retry attempts
retryDelaynumber | functionexponentialDelay between retries
selectfunction-Transform the data before returning
queryKeyarray-Additional query key segments
callConfigCallConfig-IC agent call configuration

Returns a TanStack Query result object:

PropertyTypeDescription
dataTData | undefinedThe resolved data
errorError | nullError if query failed
status'pending' | 'error' | 'success'Query status
isPendingbooleanTrue if no data yet
isErrorbooleanTrue if query errored
isSuccessbooleanTrue if query succeeded
isFetchingbooleanTrue if fetching (including background)
isRefetchingbooleanTrue if refetching
refetchfunctionManually trigger a refetch
dataUpdatedAtnumberTimestamp of last data update
const { data, isPending, error } = useActorQuery({
functionName: "greet",
args: ["World"],
})
const { data } = useActorQuery({
functionName: "getUser",
args: [userId],
enabled: !!userId, // Only fetch when userId exists
})
// Extract only the name from the user object
const { data: userName } = useActorQuery({
functionName: "getUser",
args: [userId],
select: (user) => user?.name,
})
// Data stays fresh for 5 minutes
const { data } = useActorQuery({
functionName: "getConfig",
args: [],
staleTime: 5 * 60 * 1000,
})
// Data is never stale
const { data } = useActorQuery({
functionName: "getMetadata",
args: [],
staleTime: Infinity,
})
// Refetch every 10 seconds
const { data } = useActorQuery({
functionName: "getPrice",
args: [],
refetchInterval: 10_000,
})
const { data, refetch, isFetching } = useActorQuery({
functionName: "getNotifications",
args: [],
})
return (
<div>
<NotificationList data={data} />
<button onClick={() => refetch()} disabled={isFetching}>
Refresh
</button>
</div>
)
import { CanisterError, CallError } from "@ic-reactor/core"
const { data, error, isError } = useActorQuery({
functionName: "getBalance",
args: [principal],
})
if (isError) {
if (error instanceof CanisterError) {
// Business logic error from canister
return (
<div>
Canister error [{error.code}]: {JSON.stringify(error.err)}
</div>
)
}
// Network or other error
return <div>Error: {error.message}</div>
}
// TypeScript infers types from your canister interface
const { data } = useActorQuery({
functionName: "getUser", // ✅ Autocompletes valid methods
args: ["user-123"], // ✅ Type-checked
})
// data is typed as User | undefined
// Add custom segments to the query key
const { data } = useActorQuery({
functionName: "getData",
args: [],
queryKey: ["version", "2"],
})
// Full key: [canisterId, "getData", "version", "2"]
function UserPosts({ userId }: { userId: string }) {
// First query
const { data: user } = useActorQuery({
functionName: "getUser",
args: [userId],
})
// Dependent query - only runs when user exists
const { data: posts } = useActorQuery({
functionName: "getUserPosts",
args: [user?.id ?? ""],
enabled: !!user?.id,
})
return <PostList posts={posts} />
}
useActorQuery<
M extends FunctionName<A>, // Method name
TSelected = ReturnType // Type after select
>(options: UseActorQueryConfig<A, M, T, TSelected>)

The types are automatically inferred from your actor interface, so you typically don’t need to specify them manually.