Skip to main content

Connection state

Present offline, reconnecting, and pending-operation state without confusing it with backend health.

useConvexConnectionState() observes the current primary Convex client's connection state. It returns UseConvexConnectionStateReturn; every field is a computed ref.

ts
const { state, isConnected, isReconnecting, pendingMutations, pendingActions } =
  useConvexConnectionState()

Offline banner

vue
<script setup lang="ts">
const { isConnected, isReconnecting } = useConvexConnectionState()

// This delay is a product choice, so it lives in the application.
const showOfflineBanner = ref(false)
let timer: ReturnType<typeof setTimeout> | undefined
let stopWatching: (() => void) | undefined

onMounted(() => {
  stopWatching = watch(
    isConnected,
    (connected) => {
      clearTimeout(timer)
      if (connected) {
        showOfflineBanner.value = false
        return
      }
      timer = setTimeout(() => {
        showOfflineBanner.value = true
      }, 500)
    },
    { immediate: true },
  )
})

onBeforeUnmount(() => {
  stopWatching?.()
  clearTimeout(timer)
})
</script>

<template>
  <aside v-if="showOfflineBanner" role="status">
    {{ isReconnecting ? 'Reconnecting to live updates…' : 'Live updates are offline.' }}
  </aside>
</template>

The composable reports transport facts immediately. During server rendering, and in a Nuxt build without a Convex URL, it reports the disconnected state that the browser runtime starts from, so the first browser render matches the server HTML. The example delays its banner until after mount so the application, not the library, decides when to show it.

What connection means

isConnected reports the WebSocket connection. It does not prove:

  • every backend dependency is healthy;
  • a pending mutation committed;
  • the browser has general internet access;
  • a third-party API called by an action is available.

Use operation results and product queries for those facts.

Pending operations

pendingMutations and pendingActions come from the Convex connection state. They support a general “saving” indicator, not per-form attribution.

Identity changes

When the runtime replaces the primary client, connection state resets to the disconnected snapshot and observation rebinds to the replacement. Do not preserve the old client's connected badge through the transition.

Cleanup

Mounted consumers share one underlying connection-state subscription. The runtime subscribes for the first consumer and removes it after the last scope ends.

In the browser, calling the composable outside a component or Vue effect scope throws immediately. A connection subscription must stop when its scope ends. Utility code should receive the connection state from its caller, or run inside an effect scope that it creates.