Skip to content
IC Reactor

All-in-One Demo

A simplified “Twitter-like” dApp that demonstrates the full power of IC Reactor, including optimistic UI updates, backend integration, and authentication.

  • Optimistic Updates: UI updates instantly when you “Like” a post, rolling back on error.
  • Rust Backend: Includes a simple Rust canister for posts and likes.
  • Authentication: Connect with Internet Identity.
  • Form Handling: Creating new posts with loading states.
  • Automatic Refetching: Lists update automatically after mutations.
src/lib/factories.ts
import { createMutation, createQuery } from "@ic-reactor/react"
import { backendReactor } from "../canisters/backend"
export const getLikes = createQuery(backendReactor, {
functionName: "get_likes",
refetchInterval: 3000,
})
export const likeHeart = createMutation(backendReactor, {
functionName: "like",
})

onCanisterError fires only for canister Result { Err } variants and receives two arguments — the CanisterError and the mutation variables. onError fires for every error and is the one that receives the onMutate context:

src/lib/useHeart.ts
const { mutateAsync: likeMutate } = likeHeart.useMutation({
// Canister returned { Ok }
onSuccess: () => {
addLog("success", "Like confirmed by canister")
},
// Canister returned { Err } — business logic errors only
onCanisterError: (error, variables) => {
addLog("error", `Canister rejected like: ${error.message}`)
},
// Every error, including network and agent failures
onError: (error, variables, context) => {
console.error("Like mutation error:", error)
},
onSettled: () => getLikes.invalidate(),
})

The demo uses React’s useOptimistic rather than writing into the query cache, so the optimistic state unwinds by itself when the transition settles:

const { data: likes = [] } = getLikes.useQuery()
const [optimisticLikes, addOptimisticLike] = useOptimistic(
likes,
(state, newLike: { type: "add" | "remove"; principal: string }) =>
newLike.type === "add"
? [...state, newLike.principal]
: state.filter((p) => p !== newLike.principal)
)