Picadabra Docs

React

TanStack Query integration for React applications.

Installation

npm install @picadabra/client @tanstack/react-query

Setup

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 taskId is 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?