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?