Skip to content
IC Reactor

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>
}

UseActorQueryParameters extends react-query’s QueryObserverOptions, giving you access to all standard react-query options plus our custom actor options.

Option Type Description
functionName string The canister method to call
Option Type Default Description
args array [] Arguments to pass to the method
enabled boolean true Whether the query should run
staleTime number 0 Time in ms before data is considered stale
gcTime number 300000 Time in ms before unused data is garbage collected
refetchInterval number | false false Polling interval in ms
refetchOnWindowFocus boolean true Refetch when window regains focus
refetchOnMount boolean true Refetch when component mounts
refetchOnReconnect boolean true Refetch when network reconnects
retry number | boolean 3 Number of retry attempts
retryDelay number | function exponential Delay between retries
select function - Transform the data before returning
queryKey array - Additional query key segments
callConfig CallConfig - IC agent call configuration

Returns a TanStack Query result object:

Property Type Description
data TData | undefined The resolved data
error Error | null Error if query failed
status 'pending' | 'error' | 'success' Query status
isPending boolean True if no data yet
isError boolean True if query errored
isSuccess boolean True if query succeeded
isFetching boolean True if fetching (including background)
isRefetching boolean True if refetching
refetch function Manually trigger a refetch
dataUpdatedAt number Timestamp 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/react"
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"]

The args segment is the JSON-serialized args array, so an empty args: [] still contributes the literal "[]". Custom queryKey segments are appended after it, never in place of the identity prefix.

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.