Zero provides React and SolidJS hooks for seamless integration with your UI framework.
React Hooks
Import from @rocicorp/zero-react:
import {
useQuery,
useSuspenseQuery,
useConnectionState,
useZero,
ZeroProvider
} from '@rocicorp/zero-react';
useQuery()
Subscribe to a query and receive live updates.
function MyComponent() {
const [issues, details] = useQuery(
q.issue.where('status', '=', 'open')
);
if (details.type === 'unknown') {
return <div>Loading...</div>;
}
return <div>{issues.length} open issues</div>;
}
query
Query | QueryRequest | Falsy
required
The query to subscribe to. Can be null, undefined, or false to disable the query.
options
UseQueryOptions | boolean
Query options or a boolean for enabled:interface UseQueryOptions {
enabled?: boolean; // Whether to execute the query
ttl?: TTL; // Time to live after unsubscribe
}
returns
QueryResult<TReturn> | MaybeQueryResult<TReturn>
A tuple of [data, details]:
data: Query results (undefined if query is falsy)
details: Metadata with type of 'unknown', 'complete', or 'error'
type QueryResult<T> = readonly [HumanReadable<T>, QueryResultDetails];
type MaybeQueryResult<T> = readonly [HumanReadable<T> | undefined, QueryResultDetails];
useSuspenseQuery()
Suspense-enabled query hook that suspends until data is available.
function MyComponent() {
const [issues, details] = useSuspenseQuery(
q.issue.where('status', '=', 'open'),
{ suspendUntil: 'complete' }
);
// No loading state needed - component suspends until data is ready
return <div>{issues.length} open issues</div>;
}
query
Query | QueryRequest | Falsy
required
The query to subscribe to
options
UseSuspenseQueryOptions | boolean
Suspense query options:interface UseSuspenseQueryOptions extends UseQueryOptions {
suspendUntil?: 'partial' | 'complete';
}
'partial': Suspend until partial results or complete (default)
'complete': Suspend until query fully completes
returns
QueryResult<TReturn> | MaybeQueryResult<TReturn>
Same as useQuery(), but will suspend the component until data meets the suspendUntil condition.
useConnectionState()
Subscribe to the Zero instance’s connection state.
function ConnectionIndicator() {
const state = useConnectionState();
return (
<div>
Status: {state.name}
{state.name === 'error' && <div>Error: {state.reason}</div>}
</div>
);
}
The current connection state, one of:type ConnectionState =
| {name: 'connecting', reason?: string}
| {name: 'connected'}
| {name: 'disconnected', reason: string}
| {name: 'needs-auth', reason: {...}}
| {name: 'error', reason: string}
| {name: 'closed', reason: string}
useZero()
Access the Zero instance from context.
function MyComponent() {
const z = useZero();
const handleCreate = async () => {
await z.mutate.issue.create({
id: nanoid(),
title: 'New issue'
});
};
return <button onClick={handleCreate}>Create Issue</button>;
}
returns
Zero<Schema, Mutators, Context>
The Zero instance provided by ZeroProvider
ZeroProvider
Provider component that creates and manages a Zero instance.
import { ZeroProvider } from '@rocicorp/zero-react';
function App() {
return (
<ZeroProvider
schema={schema}
userID="user-123"
auth={authToken}
cacheURL="https://myapp.zero.ms"
>
<MyComponent />
</ZeroProvider>
);
}
Child components that will have access to the Zero instance
Pass an existing Zero instance instead of creating a new one:const z = new Zero({...});
<ZeroProvider zero={z}>{children}</ZeroProvider>
Callback invoked after Zero instance is created:<ZeroProvider
schema={schema}
userID="user-123"
init={(z) => {
console.log('Zero initialized:', z.clientID);
}}
>
All ZeroOptions are also accepted as props when not providing an external zero instance.
useZeroOnline() (deprecated)
Subscribe to the online status of the Zero instance.
function OnlineIndicator() {
const isOnline = useZeroOnline();
return <div>{isOnline ? '🟢 Online' : '🔴 Offline'}</div>;
}
Deprecated: Use useConnectionState() instead for more detailed connection state.
true if Zero is online, false otherwise
SolidJS Hooks
Import from @rocicorp/zero-solid:
import {
useQuery,
createQuery,
useConnectionState,
useZero,
ZeroProvider
} from '@rocicorp/zero-solid';
useQuery()
Solid hook that creates a reactive query signal.
import { useQuery } from '@rocicorp/zero-solid';
function MyComponent() {
const [issues, details] = useQuery(() =>
q.issue.where('status', '=', 'open')
);
return (
<Show when={details().type === 'complete'} fallback={<div>Loading...</div>}>
<div>{issues().length} open issues</div>
</Show>
);
}
query
() => Query | QueryRequest | Falsy
required
A function returning the query to subscribe to. Reactive to track dependencies.
options
UseQueryOptions | boolean
Same as React’s useQuery options:interface UseQueryOptions {
enabled?: boolean;
ttl?: TTL;
}
returns
[Accessor<T>, Accessor<Details>]
A tuple of Solid signals:
data(): Access the query results
details(): Access query metadata
createQuery()
Creates a query outside of a component context.
const [issues, details] = createQuery(
z,
() => q.issue.where('status', '=', 'open'),
{ enabled: true }
);
query
() => Query | QueryRequest | Falsy
required
A function returning the query
returns
[Accessor<T>, Accessor<Details>]
Tuple of Solid signals for data and details
useConnectionState()
Solid hook for subscribing to connection state.
import { useConnectionState } from '@rocicorp/zero-solid';
function ConnectionIndicator() {
const state = useConnectionState();
return <div>Status: {state().name}</div>;
}
returns
Accessor<ConnectionState>
A Solid signal returning the current connection state
useZero()
Access the Zero instance from Solid context.
import { useZero } from '@rocicorp/zero-solid';
function MyComponent() {
const z = useZero();
const handleCreate = () => {
z.mutate.issue.create({
id: nanoid(),
title: 'New issue'
});
};
return <button onClick={handleCreate}>Create Issue</button>;
}
returns
Zero<Schema, Mutators, Context>
The Zero instance provided by ZeroProvider
ZeroProvider
Solid provider component for Zero.
import { ZeroProvider } from '@rocicorp/zero-solid';
function App() {
return (
<ZeroProvider
schema={schema}
userID="user-123"
auth={authToken}
cacheURL="https://myapp.zero.ms"
>
<MyComponent />
</ZeroProvider>
);
}
Accepts the same props as React’s ZeroProvider.
useZeroOnline() (deprecated)
Solid hook for subscribing to online status.
function OnlineIndicator() {
const isOnline = useZeroOnline();
return <div>{isOnline() ? '🟢' : '🔴'}</div>;
}
Deprecated: Use useConnectionState() instead.
A Solid signal returning the online status
Common Patterns
Conditional Queries
Disable queries by passing falsy values:
// React
const [issue, details] = useQuery(
issueId ? q.issue.where('id', '=', issueId).one() : null
);
// Solid
const [issue, details] = useQuery(() =>
issueId() ? q.issue.where('id', '=', issueId()).one() : null
);
Query TTL
Control how long queries remain cached after unmounting:
const [data, details] = useQuery(query, {
ttl: 60 // Keep cached for 60 seconds after unmount
});
Error Handling
Handle query errors with the details object:
const [data, details] = useQuery(query);
if (details.type === 'error') {
return (
<div>
<p>Error: {details.error.message}</p>
<button onClick={details.retry}>Retry</button>
</div>
);
}
Connection Management
Manually control connections from components:
function LoginButton() {
const z = useZero();
const state = useConnectionState();
const handleLogin = async () => {
const token = await getAuthToken();
await z.connection.connect({auth: token});
};
if (state.name === 'needs-auth') {
return <button onClick={handleLogin}>Login</button>;
}
return <div>Connected</div>;
}