Announcing ic-reactor v2: Now with agent-js v3 Support!
Hey everyone!
I’m thrilled to announce the release of ic-reactor v2!
This is a major update that brings full compatibility with the new, leaner, and more powerful agent-js v3.
This version is packed with significant improvements focused on boosting your dApp’s performance, enhancing developer experience, and dramatically simplifying how you handle canister responses.
What’s New in v2?
-
agent-js v3 Compatibility: ic-reactoris now built on the latest version ICP JavaScript SDK. This means your project benefits from new error handling capabilities, smaller bundle size and a more streamlined, modern API under the hood. -
Shared State & Caching: We’ve moved from component-level state to a shared state model powered by Zustand. Canister calls with the same function name and arguments now share their state across your entire application. -
Introducing compileResult(): This is a game-changer for handling Candidvarianttypes. The newcompileResulthelper function, returned by our hooks, standardizes the result into a simple object:{ isOk, value, isErr, error }. No more manually checking for'Ok'or'Err'keys!
The Power of compileResult Explained
Handling Candid variant types has never been easier. Let’s say your canister has a transfer method with this signature:
type TransferResult = variant { Ok : nat; Err : text };
service : {
transfer : (text, nat) -> (TransferResult);
}
This is a very common pattern. Now, let’s see how you’d handle calling it in v1 vs. the new and improved v2.
The Old Way (v1) - Clunky and Complex
In v1, you had to write complex rendering logic with multiple nested checks to handle loading, network errors, and the two different outcomes (Ok vs. Err) of the canister call.
// 👎 The old v1 approach
function TransferComponentV1({ to, amount }) {
const {
call: handleTransfer,
error: callError,
loading,
data,
} = useUpdateCall({
functionName: "icrc1_transfer",
args: [to, amount],
})
// All the rendering logic gets complicated quickly
const renderResult = () => {
if (loading) {
return <div>Processing transfer...</div>
}
// First, check for an agent/network error
if (callError) {
return <div>Error: {callError.message}</div>
}
// If there's data, you have to inspect it
if (data) {
// Check if the 'Ok' key exists
if ("Ok" in data) {
return <div>Success! Block index: {data.Ok.toString()}</div>
}
// Then check if the 'Err' key exists
if ("Err" in data) {
return <div>Transfer Failed: {data.Err}</div>
}
}
// Return nothing if there's no data, loading, or error
return null
}
return (
<div>
<button onClick={handleTransfer} disabled={loading}>
Transfer (v1 Style)
</button>
<div className="result-area">{renderResult()}</div>
</div>
)
}
The New Way (v2)
- Clean and Simple
With v2, the compileResult() function handles all the complexity. Your component logic becomes flat, readable, and directly focused on the result, just as it should be.
// 👍 The new v2 approach with compileResult()
import React from "react"
import { useUpdateCall } from "@ic-reactor/react" // v2 import
function TransferComponentV2({ to, amount }) {
// The hook gives you everything you need, already parsed!
const {
call: handleTransfer,
error: callError,
isLoading,
compileResult,
} = useUpdateCall({
functionName: "transfer",
args: [to, amount],
})
// compileResult() gives you a clean, standardized object to work with
const { isOk, value, isErr, error } = compileResult()
return (
<div>
<button onClick={handleTransfer} disabled={isLoading}>
{isLoading ? "Processing..." : "Transfer (v2 Style)"}
</button>
<div className="result-area">
{/* Agent/network error */}
{callError && <div>Error: {callError.message}</div>}
{/* Candid 'Ok' result is a simple boolean check */}
{isOk && <div>Success! New balance: {value.toString()}</div>}
{/* Candid 'Err' result is a simple boolean check */}
{isErr && <div>Transfer Failed: {error}</div>}
</div>
</div>
)
}
Upgrading to v2 is Easy!
We’ve worked hard to make the upgrade process from v1 as smooth as possible. You should be able to upgrade to ic-reactor v2 and have it work seamlessly with your existing code.
Your existing hooks will continue to function, but we highly recommend refactoring them to use the new compileResult helper for cleaner and more robust code.
If you run into any problems at all during the upgrade, please post about it here in this forum. We will help you solve it as soon as possible!
Happy coding!