Skip to content

What's changed in v5 ​

This page is a high-level reference of what changed between Vue Apollo v4 and v5. For a step-by-step walkthrough, see the Migration guide. For the compatibility layer that smooths the transition, see Compat layer.

Why v5 ​

Most of the surface change is driven by Apollo Client v4. Apollo Client v4 introduced:

  • A DataState discriminated union with empty / partial / complete / streaming states.
  • A new error model: the class-based ApolloError was replaced by an ErrorLike plus specific error classes (CombinedGraphQLErrors, ServerError, etc.).
  • Namespaced types (ApolloClient.MutateOptions replacing MutationOptions).
  • Native @defer and @stream support via an incremental delivery handler.

Vue Apollo v5 surfaces these in a Vue-native way. It also drops Vue 2 support: the peer dep is now Vue 3.5+, the package no longer ships through vue-demi.

Composable signature changes ​

The biggest breaking change: variables moved from a positional argument into options.

useQuery ​

v4v5
No varsuseQuery(QUERY)useQuery(QUERY)
With varsuseQuery(QUERY, { id })useQuery(QUERY, { variables: { id } })
Vars + optionsuseQuery(QUERY, { id }, { fetchPolicy: 'no-cache' })useQuery(QUERY, { variables: { id }, fetchPolicy: 'no-cache' })

useSubscription ​

Same shape change as useQuery. Variables move into options.

useMutation ​

The composable signature is unchanged: useMutation(MUTATION, options?). The change is in the mutate function:

v4v5
Mutate with varsmutate({ id, text })mutate({ variables: { id, text } })
Mutate with vars + overridesmutate({ id, text }, { fetchPolicy: 'no-cache' })mutate({ variables: { id, text }, fetchPolicy: 'no-cache' })

useLazyQuery ​

v4v5
ComposableuseLazyQuery(QUERY, { id }, options)useLazyQuery(QUERY, { variables: { id }, ...options })
load()load(undefined, { id })load({ id })
load returnfalse | Promise<TData>Promise<TData | undefined> (always a Promise)

Return-shape changes ​

v5 adds a current ref containing a discriminated union, alongside the v4-style flat refs. For useQuery and useFragment, we recommend current because resultState narrows the type of result:

ts
const { current } = useQuery(GET_USER)

if (current.value.resultState === 'complete') {
  // current.value.result is fully typed as TData
  console.log(current.value.result.user.name)
}

The flat refs (result, loading, error, networkStatus) remain available, so v4 code continues to work after the signature changes.

useMutation and useSubscription keep their flat-ref-only shape because their results do not have multiple data states.

See TypeScript: Composable return-value shapes for the full comparison.

Error type ​

The v3-era ApolloError class is gone from Apollo Client v4. v5 types error as ErrorLike | undefined:

v4v5
TypeRef<ApolloError | null>Ref<ErrorLike | undefined>
Detect kinderror instanceof ApolloErrorCombinedGraphQLErrors.is(error)
Access GraphQL errorserror.graphQLErrorsAfter narrowing with .is(), error.errors on CombinedGraphQLErrors
Access network errorerror.networkErrorAfter narrowing with .is(), the error class itself (ServerError, ServerParseError, etc.)

The error classes ship from @apollo/client/errors. See Error Handling for the full pattern.

Event hook callbacks ​

v4's onResult, onError, and onDone callbacks received a second argument { client }. v5 drops it:

ts
// v4
onResult((result, { client }) => {
  console.log(result, client)
})
onError((error, { client }) => {
  console.error(error, client)
})

// v5
onResult((result) => {
  console.log(result)
})
onError((error) => {
  console.error(error)
})

If you need the client inside the callback, use useApolloClient() from the surrounding scope.

Removed APIs ​

RemovedReplacement
useResult(result, defaultValue, picker)computed(() => result.value?.someField ?? defaultValue)
forceDisabled on useQuery returnUse start() / stop()
Reactive options on subscribeToMorewatch(...) and manually re-call subscribeToMore

useResult was already deprecated in v4 (with a console warning telling users to use computed). It is fully removed in v5.

Added APIs ​

AddedPurpose
useFragmentRead fragment data from the cache reactively via Apollo Client v4's watchFragment
current ref on useQuery and useFragmentDiscriminated union of result + state for type-safe narrowing
current.resultState'empty' | 'partial' | 'streaming' | 'complete'
awaitComplete option on useQueryWhen awaited, wait for the full streamed response rather than the first chunk
onNextState, onCompleteResult, onPartialResult, onStreamingResultGranular event hooks for state transitions and result variants

Variables reactivity ​

v4 accepted variables as a value, a ref, or a getter (the whole-object form). v5 still accepts those, and adds a per-key form so individual variable values can be reactive without wrapping the whole object:

ts
// v4 and v5 (whole-object form, still works)
useQuery(QUERY, () => ({ id: someRef.value }))

// v5 only (per-key form)
useQuery(QUERY, { variables: { id: someRef } })

In the per-key form, each value can independently be a ref, a getter, or a plain value.

Apollo Client peer dep ​

v4v5
Apollo Client^3.0.0^4.1.0
Vue^2.7.0 || ^3.0.0 (via vue-demi)^3.5.0
Removed depsvue-demi, throttle-debounce
Added deps@vueuse/core, @wry/equality, rxjs

Internal utilities that v4 maintained (paramToReactive, paramToRef, useEventHook, toApolloError, etc.) are gone in v5, replaced by VueUse primitives.

Next steps ​

Released under the MIT License.