Skip to content

createActorHooks

createActorHooks is a factory function that creates a set of type-safe React hooks bound to a specific canister. It’s the primary way to integrate IC Reactor with React.

import { createActorHooks } from "@ic-reactor/react"
import { createActorHooks } from "@ic-reactor/react"
import { backend } from "./reactor"
const {
useActorQuery,
useActorSuspenseQuery,
useActorInfiniteQuery,
useActorSuspenseInfiniteQuery,
useActorMutation,
useActorMethod,
} = createActorHooks(backend)

Using a Reactor instance is the only supported way to create actor hooks:

import { createActorHooks } from "@ic-reactor/react"
import { clientManager } from "./reactor"
import { Reactor } from "@ic-reactor/core"
import { idlFactory, type _SERVICE } from "../declarations/backend"
const backend = new Reactor<_SERVICE>({
clientManager,
idlFactory,
canisterId: import.meta.env.VITE_BACKEND_CANISTER_ID,
})
const { useActorQuery, useActorMutation } = createActorHooks(backend)

With DisplayReactor (Auto Transformations)

Section titled “With DisplayReactor (Auto Transformations)”

To enable automatic display transformations (BigInt → string, Principal → text, etc.), use DisplayReactor:

import { createActorHooks } from "@ic-reactor/react"
import { DisplayReactor } from "@ic-reactor/core"
import { clientManager } from "./reactor"
import { idlFactory, type _SERVICE } from "../declarations/backend"
const backend = new DisplayReactor<_SERVICE>({
clientManager,
idlFactory,
canisterId: "...",
})
// Hooks will use display types (string instead of bigint, etc.)
const { useActorQuery, useActorMutation } = createActorHooks(backend)
createActorHooks(reactor: Reactor<A, T>)
ParameterTypeDescription
reactorReactor<A, T>A pre-created Reactor or DisplayReactor instance

createActorHooks returns an object containing:

PropertyTypeDescription
useActorQueryHookQuery hook for fetching data
useActorSuspenseQueryHookSuspense-enabled query hook
useActorMutationHookMutation hook for updates
useActorMethodHookUnified hook for queries & updates
useActorInfiniteQueryHookInfinite query hook for pagination
useActorSuspenseInfiniteQueryHookSuspense-enabled infinite query hook
src/reactor/index.ts
import { ClientManager, Reactor } from "@ic-reactor/core"
import { QueryClient } from "@tanstack/query-core"
import { idlFactory, type _SERVICE } from "../declarations/backend"
export const queryClient = new QueryClient()
export const clientManager = new ClientManager({
queryClient,
withProcessEnv: true,
})
export const backend = new Reactor<_SERVICE>({
clientManager,
idlFactory,
canisterId: import.meta.env.VITE_BACKEND_CANISTER_ID,
name: "backend",
})
src/reactor/hooks.ts
import { createActorHooks, createAuthHooks } from "@ic-reactor/react"
import { backend, clientManager } from "./index"
// Create hooks for the backend canister
export const {
useActorQuery,
useActorMutation,
useActorSuspenseQuery,
useActorInfiniteQuery,
useActorSuspenseInfiniteQuery,
useActorMutation,
useActorMethod,
} = createActorHooks(backend)
// Create auth hooks
export const { useAuth, useUserPrincipal, useAgentState } =
createAuthHooks(clientManager)
src/reactor/hooks.ts
import { createActorHooks } from "@ic-reactor/react"
import { backend, ledger } from "./index"
// Backend canister hooks
export const backendHooks = createActorHooks(backend)
// Ledger canister hooks
export const ledgerHooks = createActorHooks(ledger)
// Export individual hooks for convenience
export const {
useActorQuery: useBackendQuery,
useActorMutation: useBackendMutation,
} = backendHooks
export const {
useActorQuery: useLedgerQuery,
useActorMutation: useLedgerMutation,
} = ledgerHooks

You can define everything in one place:

src/reactor/hooks.ts
import { createActorHooks, createAuthHooks } from "@ic-reactor/react"
import { ClientManager, Reactor } from "@ic-reactor/core"
import { QueryClient } from "@tanstack/query-core"
import { idlFactory, type _SERVICE } from "../declarations/backend"
const queryClient = new QueryClient()
const clientManager = new ClientManager({
queryClient,
withProcessEnv: true,
})
const backend = new Reactor<_SERVICE>({
clientManager,
idlFactory,
canisterId: import.meta.env.VITE_BACKEND_CANISTER_ID,
})
// Returns hooks
export const { useActorQuery, useActorMutation } = createActorHooks(backend)
export const { useAuth, useUserPrincipal } = createAuthHooks(clientManager)
// Export for use elsewhere
export { queryClient, clientManager, backend }

createActorHooks preserves full type safety:

import { createActorHooks } from "@ic-reactor/react"
import { backend } from "./reactor"
const { useActorQuery, useActorMutation } = createActorHooks(backend)
// TypeScript knows all available methods
const { data } = useActorQuery({
functionName: "getUser", // ✅ Autocomplete shows valid methods
args: ["user-123"], // ✅ Type-checked arguments
})
const { mutate } = useActorMutation({
functionName: "createUser", // ✅ Autocomplete
})
mutate([{ name: "Alice", email: "alice@example.com" }]) // ✅ Type-safe args