React
TanStack Query integration for React applications.
Installation
npm install @picadabra/client @tanstack/react-querySetup
Create a React client with TanStack Query utilities:
// lib/picadabra.ts
import { createPicadabraClient } from "@picadabra/client";
import { createPicadabraReactClient } from "@picadabra/client/react";
const client = createPicadabraClient({
baseUrl: "https://api.picadabra.ai",
credentials: () => getAuthToken(), // your auth token getter
});
export const picadabra = createPicadabraReactClient(client);Streaming with TanStack Query
Use streamedOptions to consume SSE streams with automatic state management:
import { } from "@tanstack/react-query";
import { } from "../lib/picadabra";
function ({ }: { : string }) {
const { , } = (
.stream.streamedOptions({
: { : "generate", : { } },
: true, // Auto-reconnect on disconnect
}),
);
// data is StreamEvent[], new events appended to end
const = ?.at(-1);
if ( === "pending") return <>Connecting...</>;
if (?.type === "error") return <>Error: {.error}</>;
if (?.type === "done") return <>Complete!</>;
return <>Progress: {.(?.data)}</>;
}Multiple Concurrent Streams
TanStack Query automatically manages multiple streams with distinct query keys:
import { } from "@tanstack/react-query";
import { } from "../lib/picadabra";
function ({ }: { : string }) {
const { } = (
.stream.streamedOptions({
: { : "process", : { } },
: true,
}),
);
const = ?.at(-1);
const = (?.data as { ?: number })?. ?? 0;
return (
<>
<>Task {}</>
< ={} ={100} />
</>
);
}
// Render 5 concurrent task progress bars
function ({ }: { : string[] }) {
return (
<>
{.(() => (
< ={} ={} />
))}
</>
);
}Each TaskProgress component:
- Has its own SSE connection
- Shares data if the same
taskIdis used elsewhere - Automatically cleans up when unmounted
Query Options
streamedOptions
For accumulating events (chat messages, logs):
picadabra.stream.streamedOptions({
input: { endpoint: "chat", input: { message: "Hello" } },
queryFnOptions: {
refetchMode: "reset", // 'reset' | 'append'
maxChunks: 100, // Limit stored events
},
retry: true,
});liveOptions
For latest-value only (progress, status):
picadabra.stream.liveOptions({
input: { endpoint: "status", input: { taskId } },
retry: true,
});
// data is always the latest StreamEvent (not an array)Cancellation
Streams are automatically cancelled when the component unmounts. For manual control:
import { , } from "@tanstack/react-query";
import { } from "../lib/picadabra";
function ({ }: { : string }) {
const = ();
const { } = (
.stream.streamedOptions({
: { : "process", : { } },
}),
);
const = () => {
.({
: .stream.key({
: { : "process", : { } },
}),
});
};
return (
<>
<>{.(?.at(-1))}</>
< ={}>Cancel</>
</>
);
}Error Handling
import { } from "@orpc/client";
import { } from "@tanstack/react-query";
import { } from "../lib/picadabra";
function ({ }: { : string }) {
const { , , } = (
.stream.streamedOptions({
: { : "process", : { } },
}),
);
// Connection-level error
if ( && ()) {
return <>Connection error: {.message}</>;
}
// Stream-level error (from event)
const = ?.at(-1);
if (?.type === "error") {
return <>Task error: {.error}</>;
}
return <>{.(?.data)}</>;
}How is this guide?