Skip to Content
DocumentationReferenceReact Hooks (@loopstack/react)

React Hooks

@loopstack/react connects a @loopstack/client to React through TanStack Query : typed query and mutation hooks, live cache invalidation from the backend’s event stream, and LLM token streaming. It is deliberately thin — your app owns the QueryClient, styling, and routing; the package contributes data access only.

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

Setup

Mount a LoopstackProvider inside your QueryClientProvider and enable live invalidation once:

import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { createClient } from '@loopstack/client'; import { LoopstackProvider, useLiveInvalidation } from '@loopstack/react'; const queryClient = new QueryClient(); const client = createClient({ url: 'http://localhost:3000' }); function Live({ children }) { useLiveInvalidation(); // SSE events → targeted query invalidation return children; } export function App() { return ( <QueryClientProvider client={queryClient}> <LoopstackProvider client={client}> <Live> <RunList /> </Live> </LoopstackProvider> </QueryClientProvider> ); }
import { useStartWorkflow, useWorkflowList } from '@loopstack/react'; function RunList() { const { data } = useWorkflowList({ limit: 10 }); const start = useStartWorkflow(); return ( <> <button onClick={() => start.mutate({ workflowName: 'hello', workspaceId: '…', args: { name: 'React' } })}> Run hello </button> <ul> {data?.data.map((run) => ( <li key={run.id}> {run.workflowName} — {run.status} </li> ))} </ul> </> ); }

With useLiveInvalidation mounted, the list refreshes itself as runs progress — no polling.

Query hooks

All query hooks wrap the SDK’s query descriptors and accept TanStack options (select, enabled, refetchInterval, …) with full type inference:

  • RunsuseWorkflow(id), useWorkflowStatus(id), useWorkflowList(params), useChildWorkflows(parentId), useWorkflowCheckpoints(id)
  • DocumentsuseDocument(id), useWorkflowDocuments(workflowId, params)
  • WorkspacesuseWorkspace(id), useWorkspaceList(params)
  • ConfiguseAppsConfig(), useWorkflowConfig(name), useWorkflowSource(name), useToolConfigs(), useToolConfig(name), useAvailableEnvironments()
  • Dashboard & authuseDashboardStats(), useMe(), useWorkerHealth()

Mutations

Mutations invalidate — or, where the API returns the fresh state, directly update — the affected caches:

  • ExecutionuseStartWorkflow(), useRunWorkflow() (transitions, incl. answering human-in-the-loop prompts)
  • RunsuseCreateWorkflow(), useUpdateWorkflow(), useDeleteWorkflow()
  • WorkspacesuseCreateWorkspace(), useUpdateWorkspace(), useSetFavouriteWorkspace(), useDeleteWorkspace(), useBatchDeleteWorkspaces()
  • SessionuseHubLogin(), useRefreshSession(), useLogout()

Streaming and the raw client

  • useLlmStream(workflowId) — accumulates live LLM token deltas for a run (Studio uses it for the streaming answer view).
  • useLoopstackClient() — the nearest provided LoopstackClient, for anything the hooks don’t cover.

Multiple environments

Cache keys are scoped by each client’s envKey, so several LoopstackProviders pointing at different backends can safely share a single QueryClient — Studio embedded next to your own data fetching, for example.

Last updated on