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-querySetup
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:
- Runs —
useWorkflow(id),useWorkflowStatus(id),useWorkflowList(params),useChildWorkflows(parentId),useWorkflowCheckpoints(id) - Documents —
useDocument(id),useWorkflowDocuments(workflowId, params) - Workspaces —
useWorkspace(id),useWorkspaceList(params) - Config —
useAppsConfig(),useWorkflowConfig(name),useWorkflowSource(name),useToolConfigs(),useToolConfig(name),useAvailableEnvironments() - Dashboard & auth —
useDashboardStats(),useMe(),useWorkerHealth()
Mutations
Mutations invalidate — or, where the API returns the fresh state, directly update — the affected caches:
- Execution —
useStartWorkflow(),useRunWorkflow()(transitions, incl. answering human-in-the-loop prompts) - Runs —
useCreateWorkflow(),useUpdateWorkflow(),useDeleteWorkflow() - Workspaces —
useCreateWorkspace(),useUpdateWorkspace(),useSetFavouriteWorkspace(),useDeleteWorkspace(),useBatchDeleteWorkspaces() - Session —
useHubLogin(),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 providedLoopstackClient, 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.