Quick Start
This tutorial walks you through creating your first IC Reactor integration with React. By the end, you’ll have a fully functional data-fetching setup with queries and mutations.
-
Install packages
Section titled “Install packages”Terminal window pnpm add @ic-reactor/react @icp-sdk/core @tanstack/react-queryTerminal window npm install @ic-reactor/react @icp-sdk/core @tanstack/react-queryTerminal window yarn add @ic-reactor/react @icp-sdk/core @tanstack/react-queryTerminal window bun add @ic-reactor/react @icp-sdk/core @tanstack/react-query -
Create the Reactor
Section titled “Create the Reactor”Create a central configuration file for your canister connection:
src/reactor/index.ts import { ClientManager, Reactor } from "@ic-reactor/react"import { QueryClient } from "@tanstack/react-query"import { idlFactory, type _SERVICE } from "../declarations/backend"// Create QueryClient with sensible defaultsexport const queryClient = new QueryClient({defaultOptions: {queries: {staleTime: 1000 * 60, // 1 minutegcTime: 1000 * 60 * 5, // 5 minutes},},})// Create ClientManager (handles agent and auth)export const clientManager = new ClientManager({queryClient,withProcessEnv: true, // Auto-detect local vs IC network})// Create Reactor for your canisterexport const backend = new Reactor<_SERVICE>({clientManager,idlFactory,canisterId: import.meta.env.VITE_BACKEND_CANISTER_ID,}) -
Create hooks
Section titled “Create hooks”Create reusable hooks from your Reactor:
src/reactor/hooks.ts import { createActorHooks } from "@ic-reactor/react"import { backend } from "./index"export const { useActorQuery, useActorMutation } = createActorHooks(backend) -
Fetch data with queries
Section titled “Fetch data with queries”Use
useActorQueryto fetch data from your canister:src/components/Greeting.tsx import { useActorQuery } from "../reactor/hooks"function Greeting() {const { data, isPending, error } = useActorQuery({functionName: "greet",args: ["World"],})if (isPending) return <div>Loading...</div>if (error) return <div>Error: {error.message}</div>return <h1>{data}</h1>} -
Update data with mutations
Section titled “Update data with mutations”Use
useActorMutationto call update methods:src/components/Counter.tsx import { useState } from "react"import { useActorQuery, useActorMutation } from "../reactor/hooks"import { backend } from "../reactor"function Counter() {// Query the current countconst { data: count } = useActorQuery({functionName: "getCount",})// Mutation to incrementconst { mutate, isPending } = useActorMutation({functionName: "increment",// Invalidate count after mutationinvalidateQueries: [backend.generateQueryKey({ functionName: "getCount" }),],})return (<div><p>Count: {count ?? "..."}</p><button onClick={() => mutate([])} disabled={isPending}>{isPending ? "Incrementing..." : "Increment"}</button></div>)}
Environment Variables
Section titled “Environment Variables”Set up your canister IDs in your environment file:
# .env.local (for Vite)VITE_BACKEND_CANISTER_ID=rrkah-fqaaa-aaaaa-aaaaq-cai
# Or if using CRAREACT_APP_BACKEND_CANISTER_ID=rrkah-fqaaa-aaaaa-aaaaq-caiWhat’s Next?
Section titled “What’s Next?”You now have IC Reactor working! Here’s what to explore next:
- React Setup — Complete configuration with authentication
- Queries — Deep dive into data fetching
- Mutations — Learn about updating data
- Query Caching — Master TanStack Query integration
- Type Safety — Understand the type system