Skip to content

injectConvexConnectionState

injectConvexConnectionState() exposes the Convex client’s WebSocket connectivity and in-flight request counters as a Signal. Use it for reconnecting indicators, offline-aware UI, and connectivity diagnostics.

function injectConvexConnectionState(options?: InjectConvexConnectionStateOptions): Signal<ConnectionState>;
interface InjectConvexConnectionStateOptions {
/**
* Environment injector used to create the connection state helper outside
* the current injection context.
*/
injectRef?: EnvironmentInjector;
}

The return value is a readonly Signal<ConnectionState>. It is seeded with the client’s current state and updated on every change the client publishes; the subscription is released automatically when the owning scope is destroyed.

ConnectionState is Convex’s own type, imported from convex/browser when you need to annotate it:

import { ConnectionState } from 'convex/browser';
Field Type Meaning
hasInflightRequests boolean True while at least one request (mutation or action) is outstanding.
isWebSocketConnected boolean True while the WebSocket to the Convex backend is currently connected.
timeOfOldestInflightRequest Date | null When the oldest still-outstanding request started, or null when nothing is in flight. Useful for “this is taking a while” affordances.
hasEverConnected boolean True once the client has opened a WebSocket to the “ready” state at least once. Distinguishes a first connection from a dropped one.
connectionCount number How many times this client has connected to the backend. A high number indicates trouble keeping a stable connection — server errors, bad internet, or expiring auth all force reconnects.
connectionRetries number How many times this client has tried and failed to connect.
inflightMutations number Number of mutations currently in flight.
inflightActions number Number of actions currently in flight.
connection-indicator.component.ts
import { Component, computed } from '@angular/core';
import { injectConvexConnectionState } from 'convex-angular';
@Component({
selector: 'app-connection-indicator',
template: `
<span [class]="tone()">{{ label() }}</span>
@if (state().hasInflightRequests) {
<span>{{ state().inflightMutations }} mutations, {{ state().inflightActions }} actions in flight</span>
}
`,
})
export class ConnectionIndicatorComponent {
readonly state = injectConvexConnectionState();
readonly label = computed(() => {
const state = this.state();
if (state.isWebSocketConnected) {
return state.hasInflightRequests ? 'Syncing' : 'Live';
}
// connectionRetries only advances while the client is failing to connect.
if (state.connectionRetries > 0) {
return `Reconnecting (attempt ${state.connectionRetries})`;
}
return state.hasEverConnected ? 'Offline' : 'Connecting';
});
readonly tone = computed(() => (this.state().isWebSocketConnected ? 'ok' : 'warn'));
// A connection that keeps dropping is worth surfacing even while it is up.
readonly isUnstable = computed(() => this.state().connectionCount > 3);
readonly oldestRequestAge = computed(() => {
const since = this.state().timeOfOldestInflightRequest;
return since === null ? 0 : Date.now() - since.getTime();
});
}

The interesting states are the combinations: isWebSocketConnected alone tells you the socket is up, but pairing it with hasEverConnected separates “connecting for the first time” from “we lost the connection”, and connectionRetries tells you the client is actively failing rather than idle.

During a server render the Convex client is disabled and its connection-state accessors throw. The helper detects this and returns a static, never-updating snapshot instead:

{
hasInflightRequests: false,
isWebSocketConnected: false,
timeOfOldestInflightRequest: null,
hasEverConnected: false,
connectionCount: 0,
connectionRetries: 0,
inflightMutations: 0,
inflightActions: 0,
}

No subscription is created and the value never changes for the lifetime of that render. A naive connection indicator therefore server-renders as “connecting”/“offline” and switches to the real state after hydration. If that flicker matters, render the indicator only once the client is live — for example by gating it on hasEverConnected — rather than making it the first thing a visitor sees.

The helper resolves the client through injectConvex(), so a missing provider throws:

Could not find `CONVEX`. Make sure to call `provideConvex(...)` once in your root application providers (for example, in `app.config.ts`).

Calling it outside an injection context without an injectRef throws:

injectConvexConnectionState() must be called from an injection context (for example, a component or service field initializer or constructor), or be given an explicit injector via the `injectRef` option to create it later from plain code.