Skip to content

React Hooks

All exports are available from @requence/socketql/client/react.

React-aware variant of the base createClient. Live query push updates are automatically wrapped in React’s startTransition, so they are treated as transition updates instead of urgent ones.

This prevents live query pushes from triggering a Suspense fallback while a useTransition is pending — for example, during a branch switch where downstream components may suspend to load new data.

import { createClient } from '@requence/socketql/client/react'
const client = createClient({
auth: () => ({ branch: localStorage.getItem('branch') }),
})

The function accepts all the same options as the base createClient. Internally it passes startTransition as the wrapLiveQueryUpdate option.


Wraps URQL’s Provider and manages the WebSocket connection lifecycle. Calls connect() on mount. By default, connection errors are thrown to the nearest React error boundary. Pass onConnectError to handle them manually instead.

import { SocketQLProvider } from '@requence/socketql/client/react'
<SocketQLProvider client={client}>
<App />
</SocketQLProvider>
PropTypeDescription
clientSocketQLClientThe client returned by createClient
onConnect() => voidCalled on successful connection
onConnectError(error: ConnectionError) => voidCalled on connection error. When set, errors are not thrown to the error boundary.

When no onConnectError prop is provided, the provider throws the ConnectionError during render. Wrap it in an error boundary to handle rejections:

<ErrorBoundary fallback={<LoginPage />}>
<SocketQLProvider client={client}>
<App />
</SocketQLProvider>
</ErrorBoundary>

The same client can be reused after the error boundary resets — the provider will re-register its listeners and call connect() again.

Pass onConnectError to handle connection errors without an error boundary. This is useful when you want to call client.reconnect() after updating auth state:

<SocketQLProvider
client={client}
onConnectError={(err) => {
console.log(err.data) // e.g. { code: 'EXPIRED' }
refreshToken().then(() => client.reconnect())
}}
>
<App />
</SocketQLProvider>
import type { SocketQLClient } from '@requence/socketql/client/react'

Suspense-ready query hook. Throws on errors (use with an error boundary).

function useQuery<Data, Variables>(
args: UseQueryArgs<Variables, Data>
): readonly [Data, reexecuteFn]

Accepts all URQL UseQueryArgs options:

OptionTypeDescription
queryDocumentInputThe GraphQL query document
variablesVariablesQuery variables
requestPolicystringURQL request policy
pausebooleanPause the query

Returns a tuple of [data, reexecute]. data is the query result, and reexecute is a function to trigger a query execution. Throws the URQL error if the query fails.


Suspense-aware mutation hook with cache invalidation support.

function useMutation<Data, Variables>(
args: UseMutationArgs<Data, Variables>
): readonly [OperationResult, executeFn]
OptionTypeDefaultDescription
queryDocumentInputThe mutation document
invalidatestring | DocumentNode | ArrayQueries to invalidate on success
suspensebooleantrueWhether to trigger Suspense during execution
waitOnstring | DocumentNode | Array | FunctionWait for a query/subscription to emit, or resolve when a predicate returns true
waitOnTimeoutnumberTimeout in milliseconds to resolve the wait lock early

A tuple of [result, execute], same as URQL’s useMutation.

waitOn accepts a query/subscription name (string), a DocumentNode, or an array of names/documents. The mutation’s Suspense lock is held until one result for each specified operation flows through the exchange pipeline — which works for both queries and subscriptions, since all results pass through the same exchange chain.

// Wait for a live query to re-emit after invalidation
const [, executeCreate] = useMutation({
query: CREATE_USER_MUTATION,
invalidate: 'Users',
waitOn: 'Users',
})
// Wait for a subscription event (e.g. list updated via subscription)
const [, executeDuplicate] = useMutation({
query: DUPLICATE_ITEM_MUTATION,
waitOn: ITEM_CHANGES_SUBSCRIPTION,
waitOnTimeout: 3000,
})

For fine-grained control — such as waiting for a subscription event that matches an ID returned by the mutation — pass a predicate function. It receives the mutation result as its first argument, followed by each incoming OperationResult and the pre-computed operation name. It resolves as soon as it returns true.

// waitOn type when a function:
// (
// mutationResult: OperationResult<Data, Variables>,
// result: OperationResult,
// operationName: string | undefined,
// ) => boolean
const [, executeCreate] = useMutation({
query: CREATE_ITEM_MUTATION,
waitOn: (mutationResult, result, name) =>
name === 'ItemCreated' &&
result.data?.itemCreated?.id === mutationResult.data?.createItem?.id,
waitOnTimeout: 5000,
})

Thin wrapper around URQL’s useSubscription. Throws on errors (use with an error boundary).

function useSubscription<Data, Result, Variables>(
args: UseSubscriptionArgs<Variables, Data>,
handler?: SubscriptionHandler<Data, Result>
): readonly [Result | undefined, executeFn]
OptionTypeDescription
argsUseSubscriptionArgs<Variables, Data>URQL subscription arguments
handlerSubscriptionHandler<Data, Result>Optional handler to accumulate data across events

args accepts all URQL UseSubscriptionArgs options:

OptionTypeDescription
queryDocumentInputThe GraphQL subscription document
variablesVariablesSubscription variables
pausebooleanPause the subscription

A tuple of [data, execute]. data is the latest subscription result (or the accumulated result when using a handler). Throws the URQL error if the subscription encounters an error.