NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #4032 most downloaded on npm
A fully-featured caching GraphQL client.
Last release today
18 Sep 2026
Ships fairly regularly
a new release about every 2 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
27 versions withdrawn
withdrawn after publishing
7 years old
727 releases · first in 2019
If you are using with addTypename={false}, ensure that your mocked responses include a __typename field. This will ensure cache normalization kicks in
#12384 6aa6fd3 Thanks @jerelmiller! - Remove the asyncMap utility function. Instead use one of the RxJS operators that creates Observables from promises, such as from.
#12398 8cf5077 Thanks @jerelmiller! - Removes the isApolloError utility function to check if the error object is an ApolloError instance. Use instanceof to check for more specific error types that replace ApolloError.
#12379 ef892b4 Thanks @jerelmiller! - Removes the addTypename option from InMemoryCache and MockedProvider. __typename is now always added to the outgoing query document when using InMemoryCache and cannot be disabled.
If you are using <MockedProvider /> with addTypename={false}, ensure that your mocked responses include a __typename field. This will ensure cache normalization kicks in and behaves more like production.
#12396 00f3d0a Thanks @jerelmiller! - Remove the deprecated errors property from useQuery and useLazyQuery. Read errors from the error property instead.
#12222 d1a9054 Thanks @jerelmiller! - Drop support for React 16.
#12376 a0c996a Thanks @jerelmiller! - Remove deprecated ignoreResults option from useMutation. If you don't want to synchronize component state with the mutation, use useApolloClient to access your client instance and use client.mutate directly.
#12384 6aa6fd3 Thanks @jerelmiller! - Unusubscribing from ObservableQuery while a request is in flight will no longer terminate the request by unsubscribing from the link observable.
#12367 e6af35e Thanks @jerelmiller! - The previousData property on useLazyQuery will now change only when data changes. Previously previousData would change to the same value as data while the query was loading.
#12224 51e6c0f Thanks @jerelmiller! - Remove deprecated partialRefetch option.
#12407 8b1390b Thanks @jerelmiller! - Calling refetch with new variables will now set the networkStatus to refetch instead of setVariables.
#12384 6aa6fd3 Thanks @jerelmiller! - Remove the iterateObserversSafely utility function.
#12398 8cf5077 Thanks @jerelmiller! - Apollo Client no longer wraps errors in ApolloError. ApolloError has been replaced with separate error classes depending on the cause of the error. As such, APIs that return an error property have been updated to use the generic Error type. Use instanceof to check for more specific error types.
ApolloError encapsulated 4 main error properties. The type of error would determine which property was set:
graphqlErrors - Errors returned from the errors field by the GraphQL servernetworkError - Any non-GraphQL error that caused the query to failprotocolErrors - Transport-level errors that occur during multipart HTTP subscriptionsclientErrors - A space to define custom errors. Mostly unused.These errors were mutally exclusive, meaning both networkError and graphqlErrors were never set simultaneously. The following replaces each of these fields from ApolloError.
graphqlErrorsGraphQL errors are now encapsulated in a CombinedGraphQLErrors instance. You can access the raw GraphQL errors via the errors property.
import { CombinedGraphQLErrors } from "@apollo/client";
// ...
const { error } = useQuery(query);
if (error && error instanceof CombinedGraphQLErrors) {
console.log(error.errors);
}
networkErrorNetwork errors are no longer wrapped and are instead passed through directly.
const client = new ApolloClient({
link: new ApolloLink(() => {
return new Observable((observer) => {
observer.error(new Error("Test error"));
});
}),
});
// ...
const { error } = useQuery(query);
// error is `new Error('Test error')`;
protocolErrorsProtocol errors are now encapsulated in a CombinedProtocolErrors instance. You can access the raw protocol errors via the errors property.
import { CombinedProtocolErrors } from "@apollo/client";
// ...
const { error } = useSubscription(subscription);
if (error && error instanceof CombinedProtocolErrors) {
console.log(error.errors);
}
clientErrorsThese were unused by the client and have no replacement. Any non-GraphQL or non-protocol errors are now passed through unwrapped.
If the link sends a string error, Apollo Client will wrap this in an Error instance. This ensures error properties are guaranteed to be of type Error.
const client = new ApolloClient({
link: new ApolloLink(() => {
return new Observable((observer) => {
// Oops we sent a string instead of wrapping it in an `Error`
observer.error("Test error");
});
}),
});
// ...
const { error } = useQuery(query);
// The error string is wrapped and returned as `new Error('Test error')`;
If the link chain sends any other object type as an error, Apollo Client will wrap this in an UnknownError instance with the cause set to the original object. This ensures error properties are guaranteed to be of type Error.
const client = new ApolloClient({
link: new ApolloLink(() => {
return new Observable((observer) => {
observer.error({ message: "Not a proper error type" });
});
}),
});
// ...
const { error } = useQuery(query);
// error is an `UnknownError` instance. error.cause returns the original object.
#12384 6aa6fd3 Thanks @jerelmiller! - Remove fromError utility function. Use throwError instead.
#12211 c2736db Thanks @jerelmiller! - Remove the deprecated graphql, withQuery, withMutation, withSubscription, and withApollo hoc components. Use the provided React hooks instead.
#12262 10ef733 Thanks @jerelmiller! - Remove itAsync test utility.
#12398 8cf5077 Thanks @jerelmiller! - Updates the ServerError and ServerParseError types to be proper Error subclasses. Perviously these were plain Error intances with additional properties added at runtime. All properties are retained, but instanceof checks now work correctly.
import { ServerError, ServerParseError } from "@apollo/client";
if (error instanceof ServerError) {
// ...
}
if (error instanceof ServerParseError) {
// ...
}
#12367 e6af35e Thanks @jerelmiller! - useLazyQuery no longer supports SSR environments and will now throw if the execute function is called in SSR. If you need to run a query in an SSR environment, use useQuery instead.
#12367 e6af35e Thanks @jerelmiller! - The execute function returned from useLazyQuery now only supports the context and variables options. This means that passing options supported by the hook no longer override the hook value.
To change options, rerender the component with new options. These options will take effect with the next query execution.
#12384 6aa6fd3 Thanks @jerelmiller! - ObservableQuery will no longer terminate on errors and will instead emit a next value with an error property. This ensures that ObservableQuery instances can continue to receive updates after errors are returned in requests without the need to resubscribe to the observable.
#12398 8cf5077 Thanks @jerelmiller! - Removes the throwServerError utility function. Now that ServerError is an
Error subclass, you can throw these errors directly:
import { ServerError } from "@apollo/client";
// instead of
throwServerError(response, result, "error message");
// Use
throw new ServerError("error message", { response, result });
#12304 86469a2 Thanks @jerelmiller! - The Cache.DiffResult<T> type is now a union type with better type safety for both complete and partial results. Checking diff.complete will now narrow the type of result depending on whether the value is true or false.
When true, diff.result will be a non-null value equal to the T generic type. When false, diff.result now reports result as DeepPartial<T> | null indicating that fields in the result may be missing (DeepPartial<T>) or empty entirely (null).
#12396 00f3d0a Thanks @jerelmiller! - Remove the errors property from the results emitted from ObservableQuery or returned from client.query. Read errors from the error property instead.
#12367 e6af35e Thanks @jerelmiller! - The result resolved from the promise returned from the execute function in useLazyQuery is now an ApolloQueryResult type and no longer includes all the fields returned from the useLazyQuery hook tuple.
If you need access to the additional properties such as called, refetch, etc. not included in ApolloQueryResult, read them from the hook instead.
#12367 e6af35e Thanks @jerelmiller! - useLazyQuery will no longer rerender with the loading state when calling the execute function the first time unless the notifyOnNetworkStatusChange option is set to true (which is the new default).
If you prefer the behavior from 3.x, rerender the component with
notifyOnNetworkStatusChange set to false after the execute function is
called the first time.
function MyComponent() {
const [notifyOnNetworkStatusChange, setNotifyOnNetworkStatusChange] =
useState(true);
const [execute] = useLazyQuery(query, { notifyOnNetworkStatusChange });
async function runExecute() {
await execute();
// Set to false after the initial fetch to stop receiving notifications
// about changes to the loading states.
setNotifyOnNetworkStatusChange(false);
}
// ...
}
#12254 0028ac0 Thanks @jerelmiller! - Changes the default Accept header to application/graphql-response+json.
#12430 2ff66d0 Thanks @jerelmiller! - ObservableQuery.setVariables will now resolve with the last emitted result instead of undefined when either the variables match the current variables or there are no subscribers to the query.
#12385 cad5117 Thanks @phryneas! - Apollo Client now defaults to production mode, not development mode, if the
environment cannot be determined.
In modern bundlers, this should automatically be handled by the bundler loading
the bundler with the development export condition.
If neither the production nor the development export condition are
used by the bundler/runtime, Apollo Client will fall back to globalThis.__DEV__
to determine if it should run in production or development mode.
Unlike Apollo Client 3 though, if globalThis.__DEV__ is not set to true,
Apollo Client will now default to production, not to development, behaviour.
This switch to explicilty requiring true also resolves a situation where
an HTML element with id="__DEV__" would create a global __DEV__ variable
with a referent to the DOM element, which in the past was picked up as "truthy" and
would have triggered development mode.
#12367 e6af35e Thanks @jerelmiller! - The reobserve option is no longer available in the result returned from useLazyQuery. This was considered an internal API and should not be used directly.
#12333 3e4beaa Thanks @jerelmiller! - Fix type of data property on ApolloQueryResult. Previously this field was non-optional, non-null TData, however at runtime this value could be set to undefined. This field is now reported as TData | undefined.
This will affect you in a handful of places:
data property emitted from the result passed to the next callback from client.watchQueryApolloQueryResult type such as observableQuery.refetch, observableQuery.fetchMore, etc.#12367 e6af35e Thanks @jerelmiller! - The promise returned when calling the execute function from useLazyQuery will now reject when using an errorPolicy of none when GraphQL errors are returned from the result.
#12223 69c1cb6 Thanks @jerelmiller! - Remove subscribeAndCount testing utility from @apollo/client/testing.
#12300 4d581e4 Thanks @jerelmiller! - Moves all React-related exports to the @apollo/client/react entrypoint and out of the main @apollo/client entrypoint. This prevents the need to install React in order to use the core client.
The following is a list of exports available in @apollo/client that should now import from @apollo/client/react.
ApolloConsumerApolloProvidercreateQueryPreloadergetApolloContextskipTokenuseApolloClientuseBackgroundQueryuseFragmentuseLazyQueryuseLoadableQueryuseMutationuseQueryuseQueryRefHandlersuseReactiveVaruseReadQueryuseSubscriptionuseSuspenseQueryThe following is a list of exports available in @apollo/client/testing that should now import from @apollo/client/testing/react:
MockedProvider#12428 abed922 Thanks @jerelmiller! - Removes the urql multipart subscriptions utilities. Use the native multipart subscriptions support in urql instead.
#12384 6aa6fd3 Thanks @jerelmiller! - Switch to RxJS as the observable implementation. rxjs is now a peer dependency of Apollo Client which means you will now need to install rxjs in addition to @apollo/client.
This change is mostly transparent, however transforming values on observables, common in link implementations, differs in RxJS vs zen-observable. For example, you could modify values in the link chain emitted from a downstream link by using the .map function. In RxJS, this is done with the .pipe function and passing a map operator instead.
import { map } from "rxjs";
const link new ApolloLink((operation, forward) => {
return forward(operation).pipe(
map((result) => performTransform(result))
);
});
For a full list of operators and comprehensive documentation on the capabilities of RxJS, check out the documentation.
#12329 61febe4 Thanks @phryneas! - Rework package publish format (#12329, #12382)
We have reworked the way Apollo Client is packaged.
"since 2023, node >= 20, not dead")package.json files, e.g. cache/core/package.json and react/package.json. While these helped with older build tools, modern build tooling uses the exports field in the root package.json instead and the presence of these files can confuse modern build tooling. If your build tooling still relies on those, please update your imports to import from e.g. @apollo/client/cache/core/index.js instead of @apollo/client/cache/core - but generally, this should not be necessary.exports field to package.json to expose entry pointsglobalThis.__DEV__, Apollo Client now primarily relies on the development and production exports conditions. It falls back to globalThis.__DEV__ if the bundler doesn't know these, though.#12397 2545a54 Thanks @jerelmiller! - Remove ObservableQuery.resetQueryStoreErrors method. This method reset some internal state that was not consumed elsewhere in the client and resulted in a no-op.
#12384 6aa6fd3 Thanks @jerelmiller! - Remove fromPromise utility function. Use from instead.
#12388 0d825be Thanks @jerelmiller! - Require environments that support WeakMap, WeakSet and symbols. Apollo Client would fallback to Map and Set if the weak versions were not available. This has been removed and expects that these features are available in the source environment.
If you are running in an environment without WeakMap, WeakSet or symbols, you will need to find appropriate polyfills.
#12367 e6af35e Thanks @jerelmiller! - useLazyQuery no longer supports calling the execute function in render and will now throw. If you need to execute the query immediately, use useQuery instead or move the call to a useEffect.
#12367 e6af35e Thanks @jerelmiller! - The defaultOptions and initialFetchPolicy options are no longer supported with useLazyQuery.
If you use defaultOptions, pass those options directly to the hook instead. If you use initialFetchPolicy, use fetchPolicy instead.
#12367 e6af35e Thanks @jerelmiller! - useLazyQuery no longer supports variables in the hook options and therefore no longer performs variable merging. The execute function must now be called with variables instead.
function MyComponent() {
const [execute] = useLazyQuery(query);
function runExecute() {
execute({ variables: { ... }});
}
}
This change means the execute function returned from useLazyQuery is more type-safe. The execute function will require you to pass a variables option if the query type includes required variables.
#12304 86469a2 Thanks @jerelmiller! - ### Changes for users of InMemoryCache
cache.diff now returns null instead of an empty object ({}) when returnPartialData is true and the result is empty.
If you use cache.diff directly with returnPartialData: true, you will need to check for null before accessing any other fields on the result property. A non-null value indicates that at least one field was present in the cache for the given query document.
The client now expects cache.diff to return null instead of an empty object when there is no data that can be fulfilled from the cache and returnPartialData is true. If your cache implementation returns an empty object, please update this to return null.
#12430 2ff66d0 Thanks @jerelmiller! - Removes ObservableQuery.result() method. If you use this method and need similar functionality, use the firstValueFrom helper in RxJS.
import { firstValueFrom, from } from "rxjs";
// The `from` is necessary to turn `observableQuery` into an RxJS observable
const result = await firstValueFrom(from(observableQuery));
#12359 ebb4d96 Thanks @jerelmiller! - Remove the onCompleted and onError callbacks from useQuery and useLazyQuery.
See #12352 for more context on this change.
#12384 6aa6fd3 Thanks @jerelmiller! - Subscriptions are no longer eagerly started after calling client.subscribe. To kick off the subscription, you will now need to subscribe to the returned observable.
// Subscriptions are no longer started when calling subscribe on its own.
const subscriptionObservable = client.subscribe(...);
// Instead, subscribe to the returned observable to kick off the subscription.
subscriptionObservable.subscribe({
next: (value) => console.log(value)
});
#12367 e6af35e Thanks @jerelmiller! - useLazyQuery will now only execute the query when the execute function is called. Previously useLazyQuery would behave like useQuery after the first call to the execute function which means changes to options might perform network requests.
You can now safely rerender useLazyQuery with new options which will take effect the next time you manually trigger the query.
#12384 6aa6fd3 Thanks @jerelmiller! - Remove toPromise utility function. Use firstValueFrom instead.
#12304 86469a2 Thanks @jerelmiller! - ### Changes for users of InMemoryCache
cache.diff no longer throws when returnPartialData is set to false without a complete result. Instead, cache.diff will return null when it is unable to read a full cache result.
If you use cache.diff directly with returnPartialData: false, remove the try/catch block and replace with a check for null.
The client now expects cache.diff to return null instead of throwing when the cache returns an incomplete result and returnPartialData is false. The internal try/catch blocks have been removed around cache.diff. If your cache implementation throws for incomplete results, please update this to return null.
#12211 c2736db Thanks @jerelmiller! - Remove the deprecated Query, Mutation, and Subscription components. Use the provided React hooks instead.
#12385 cad5117 Thanks @phryneas! - Apollo Client is no longer using ts-invariant, but ships with a modified variant of it.
The existing export setLogVerbosity from @apollo/client is still available and
now points to this new integration.
In most cases, you should be using this export.
It will no longer adjust the verbosity of ts-invariant and as such no longer
influence other packages relying on ts-invariant.
The new entry point @apollo/client/utilities/invariant now exports invariant,
InvariantError and setVerbosity.
(Note that these tools are mostly meant to be used by Apollo Client and libraries directly
based on Apollo Client like the @apollo/client-integration-* packages.)
#12333 3e4beaa Thanks @jerelmiller! - Deprecate the partial flag on ApolloQueryResult and make it a non-optional property. Previously partial was only set conditionally if the result emitted was partial. This value is now available with all results that return an ApolloQueryResult.
#12291 ae5d06a Thanks @phryneas! - Remove deprecated resetApolloContext export
#12402 903c3ef Thanks @jerelmiller! - Use an an empty object ({}) rather than an object with null prototype (Object.create(null)) in all areas that instantiate objects.
#12385 cad5117 Thanks @phryneas! - * dropped the deprecated DEV export from @apollo/client/utilities and @apollo/client/utilities/globals
__DEV__ export from @apollo/client/utilities/globals to @apollo/client/utilities/environmentinvariant, newInvariantError and InvariantError exports from @apollo/client/utilities/globals to @apollo/client/utilities/invariant#12432 c7c2f61 Thanks @phryneas! - ObservableQuery: implement the rxjs InteropObservable interface to ensure from(observableQuery) stays possible
#12385 cad5117 Thanks @phryneas! - @apollo/client, @apollo/client/core and @apollo/client/cache no longer export an empty Cache runtime object. This is meant to be a type-only namespace.
#12384 6aa6fd3 Thanks @jerelmiller! - Don't emit a partial cache result from cache-only queries when returnPartialData is false.
One column per quarter.
### Patch Changes - #13168 `6b84ec0` Thanks @jerelmiller! - Fix issue where muting a deprecation from one entrypoint would not mute the warning when c
#13168 6b84ec0 Thanks @jerelmiller! - Fix issue where muting a deprecation from one entrypoint would not mute the warning when checked in a different entrypoint. This caused some rogue deprecation warnings to appear in the console even though the warnings should have been muted.
#12970 f91fab5 Thanks @acemir! - Add a deprecation message for the variableMatcher option in MockLink.
#13168 6b84ec0 Thanks @jerelmiller! - Ensure deprecation warnings are properly silenced in React hooks when globally disabled.
### Minor Changes - #12752 `8b779b4` Thanks @jerelmiller! - Add deprecations and warnings to remaining APIs changed in Apollo Client 4.0. - #12746 `0b
#12752 8b779b4 Thanks @jerelmiller! - Add deprecations and warnings to remaining APIs changed in Apollo Client 4.0.
#12746 0bcd2f4 Thanks @jerelmiller! - Add warnings and deprecations for options and methods for all React APIs.
#12751 567cad8 Thanks @jerelmiller! - Add @deprecated tags to all properties returned from any query API (e.g. client.query, observableQuery.refetch, etc.), client.mutate, and client.subscribe that are no longer available in Apollo Client 4.0.
#12746 0bcd2f4 Thanks @jerelmiller! - Add preloadQuery.toPromise(queryRef) as a replacement for queryRef.toPromise(). queryRef.toPromise() has been removed in Apollo Client 4.0 in favor of preloadQuery.toPromise and is now considered deprecated.
#12736 ea89440 Thanks @jerelmiller! - Add deprecations and deprecation warnings for ApolloClient options and methods.
#12763 5de6a3d Thanks @jerelmiller! - Version bump only to release latest as rc.
#12459 1c5a031 Thanks @jerelmiller! - Reset addTypenameTransform and fragments caches when calling cache.gc() only when resetResultCache is true.
#12743 92ad409 Thanks @jerelmiller! - Add deprecations and warnings for addTypename in InMemoryCache and MockedProvider.
#12743 92ad409 Thanks @jerelmiller! - Add deprecations and warnings for canonizeResults.
#12751 567cad8 Thanks @jerelmiller! - Warn when using a standby fetch policy with client.query.
### Minor Changes - #12763 `5de6a3d` Thanks @jerelmiller! - Version bump only to release latest as rc.
5de6a3d Thanks @jerelmiller! - Version bump only to release latest as rc.### Minor Changes - #12752 `8b779b4` Thanks @jerelmiller! - Add deprecations and warnings to remaining APIs changed in Apollo Client 4.0. - #12751 `56
#12752 8b779b4 Thanks @jerelmiller! - Add deprecations and warnings to remaining APIs changed in Apollo Client 4.0.
#12751 567cad8 Thanks @jerelmiller! - Add @deprecated tags to all properties returned from any query API (e.g. client.query, observableQuery.refetch, etc.), client.mutate, and client.subscribe that are no longer available in Apollo Client 4.0.
#12751 567cad8 Thanks @jerelmiller! - Warn when using a standby fetch policy with client.query.
### Minor Changes - #12746 `0bcd2f4` Thanks @jerelmiller! - Add warnings and deprecations for options and methods for all React APIs. - #12746 `0bcd2f
#12746 0bcd2f4 Thanks @jerelmiller! - Add warnings and deprecations for options and methods for all React APIs.
#12746 0bcd2f4 Thanks @jerelmiller! - Add preloadQuery.toPromise(queryRef) as a replacement for queryRef.toPromise(). queryRef.toPromise() has been removed in Apollo Client 4.0 in favor of preloadQuery.toPromise and is now considered deprecated.
#12736 ea89440 Thanks @jerelmiller! - Add deprecations and deprecation warnings for ApolloClient options and methods.
#12459 1c5a031 Thanks @jerelmiller! - Reset addTypenameTransform and fragments caches when calling cache.gc() only when resetResultCache is true.
#12743 92ad409 Thanks @jerelmiller! - Add deprecations and warnings for addTypename in InMemoryCache and MockedProvider.
#12743 92ad409 Thanks @jerelmiller! - Add deprecations and warnings for canonizeResults.
### Patch Changes - #12804 `32c9aa9` Thanks @phryneas! - Fix a possible race condition on queries that were reobserved before they were subscribed to
Nothing published for this version
### Patch Changes - #12567 `c19d415` Thanks @thearchitector! - Fix in-flight multipart urql subscription cancellation
c19d415 Thanks @thearchitector! - Fix in-flight multipart urql subscription cancellation### Patch Changes - #12540 `0098932` Thanks @phryneas! - Refactor: Move notification scheduling logic from QueryInfo to ObservableQuery - #12540 `0098
### Patch Changes - #12285 `cdc55ff` Thanks @phryneas! - keep ObservableQuery created by useQuery non-active before it is first subscribed
### Patch Changes - #12461 `12c8d06` Thanks @jerelmiller! - Fix an issue where a cache-first query would return the result for previous variables when
12c8d06 Thanks @jerelmiller! - Fix an issue where a cache-first query would return the result for previous variables when a cache update is issued after simultaneously changing variables and skipping the query.### Patch Changes - #12420 `fee9368` Thanks @jorenbroekema! - Use import star from rehackt to prevent issues with importing named exports from externa
fee9368 Thanks @jorenbroekema! - Use import star from rehackt to prevent issues with importing named exports from external CJS modules.This bug also affected the useQuery and useLazyQuery hooks and may affect you if you check for networkStatus in your component.
#12362 f6d387c Thanks @jerelmiller! - Fixes an issue where calling observableQuery.getCurrentResult() when the errorPolicy was set to all would return the networkStatus as NetworkStatus.ready when there were errors returned in the result. This has been corrected to report NetworkStatus.error.
This bug also affected the useQuery and useLazyQuery hooks and may affect you if you check for networkStatus in your component.
### Patch Changes - #12409 `6aa2f3e` Thanks @phryneas! - To mitigate problems when Apollo Client ends up more than once in the bundle, some unique sym
#12409 6aa2f3e Thanks @phryneas! - To mitigate problems when Apollo Client ends up more than once in the bundle, some unique symbols were converted into Symbol.for calls.
#12392 644bb26 Thanks @Joja81! - Fixes an issue where the DeepOmit type would turn optional properties into required properties. This should only affect you if you were using the omitDeep or stripTypename utilities exported by Apollo Client.
#12404 4332b88 Thanks @jerelmiller! - Show NaN rather than converting to null in debug messages from MockLink for unmatched variables values.
### Patch Changes - #12369 `bdfc5b2` Thanks @phryneas! - ObervableQuery.refetch: don't refetch with cache-and-network, swich to network-only instead -
onCompleted and onError in useQuery and useLazyQuery have been deprecated for multiple reasons. See below for full details 👀
Apollo Client v3.13.0 introduces a new hook, useSuspenseFragment, as a drop-in replacement for useFragment in apps that are using React Suspense. This is the “last” React hook we are introducing in 3.x - we think this rounds out the “big concepts” in our React Suspense and GraphQL fragment story. See the docs for information on this and our other Suspense-supporting hooks. There are some TypeScript quality-of-life improvements shipped in this release for observableQuery.updateQuery and subscribeToMore. Additionally, the return type of updateQuery now includes undefined to allow an early exit from updates. This was always supported at runtime, but was missed on the TypeScript side. On the runtime side, we’ve fixed query deduplication behavior for multipart responses and corrected the error handling in useMutation callbacks. onCompleted and onError in useQuery and useLazyQuery have been deprecated for multiple reasons. See below for full details 👀
#12066 c01da5d Thanks @jerelmiller! - Adds a new useSuspenseFragment hook.
useSuspenseFragment suspends until data is complete. It is a drop-in replacement for useFragment when you prefer to use Suspense to control the loading state of a fragment. See the documentation for more details.
#12174 ba5cc33 Thanks @jerelmiller! - Ensure errors thrown in the onCompleted callback from useMutation don't call onError.
#12340 716d02e Thanks @phryneas! - Deprecate the onCompleted and onError callbacks of useQuery and useLazyQuery.
For more context, please see the related issue on GitHub.
#12276 670f112 Thanks @Cellule! - Provide a more type-safe option for the previous data value passed to observableQuery.updateQuery. Using it could result in crashes at runtime as this callback could be called with partial data even though its type reported the value as a complete result.
The updateQuery callback function is now called with a new type-safe previousData property and a new complete property in the 2nd argument that determines whether previousData is a complete or partial result.
As a result of this change, it is recommended to use the previousData property passed to the 2nd argument of the callback rather than using the previous data value from the first argument since that value is not type-safe. The first argument is now deprecated and will be removed in a future version of Apollo Client.
observableQuery.updateQuery(
(unsafePreviousData, { previousData, complete }) => {
previousData;
// ^? TData | DeepPartial<TData> | undefined
if (complete) {
previousData;
// ^? TData
} else {
previousData;
// ^? DeepPartial<TData> | undefined
}
}
);
#12174 ba5cc33 Thanks @jerelmiller! - Reject the mutation promise if errors are thrown in the onCompleted callback of useMutation.
#12276 670f112 Thanks @Cellule! - Fix the return type of the updateQuery function to allow for undefined. updateQuery had the ability to bail out of the update by returning a falsey value, but the return type enforced a query value.
observableQuery.updateQuery(
(unsafePreviousData, { previousData, complete }) => {
if (!complete) {
// Bail out of the update by returning early
return;
}
// ...
}
);
#12296 2422df2 Thanks @Cellule! - Deprecate option ignoreResults in useMutation.
Once this option is removed, existing code still using it might see increase in re-renders.
If you don't want to synchronize your component state with the mutation, please use useApolloClient to get your ApolloClient instance and call client.mutate directly.
#12338 67c16c9 Thanks @phryneas! - In case of a multipart response (e.g. with @defer), query deduplication will
now keep going until the final chunk has been received.
#12276 670f112 Thanks @Cellule! - Fix the type of the variables property passed as the 2nd argument to the subscribeToMore callback. This was previously reported as the variables type for the subscription itself, but is now properly typed as the query variables.
…is not type-safe. The first argument is now deprecated and will be removed in a future version of Apollo Client.
#12066 c01da5d Thanks @jerelmiller! - Adds a new useSuspenseFragment hook.
useSuspenseFragment suspends until data is complete. It is a drop-in replacement for useFragment when you prefer to use Suspense to control the loading state of a fragment.
#12174 ba5cc33 Thanks @jerelmiller! - Ensure errors thrown in the onCompleted callback from useMutation don't call onError.
#12340 716d02e Thanks @phryneas! - Deprecate the onCompleted and onError callbacks of useQuery and useLazyQuery.
For more context, please see the related issue on GitHub.
#12276 670f112 Thanks @Cellule! - Provide a more type-safe option for the previous data value passed to observableQuery.updateQuery. Using it could result in crashes at runtime as this callback could be called with partial data even though its type reported the value as a complete result.
The updateQuery callback function is now called with a new type-safe previousData property and a new complete property in the 2nd argument that determines whether previousData is a complete or partial result.
As a result of this change, it is recommended to use the previousData property passed to the 2nd argument of the callback rather than using the previous data value from the first argument since that value is not type-safe. The first argument is now deprecated and will be removed in a future version of Apollo Client.
observableQuery.updateQuery(
(unsafePreviousData, { previousData, complete }) => {
previousData;
// ^? TData | DeepPartial<TData> | undefined
if (complete) {
previousData;
// ^? TData
} else {
previousData;
// ^? DeepPartial<TData> | undefined
}
}
);
#12174 ba5cc33 Thanks @jerelmiller! - Reject the mutation promise if errors are thrown in the onCompleted callback of useMutation.
#12276 670f112 Thanks @Cellule! - Fix the return type of the updateQuery function to allow for undefined. updateQuery had the ability to bail out of the update by returning a falsey value, but the return type enforced a query value.
observableQuery.updateQuery(
(unsafePreviousData, { previousData, complete }) => {
if (!complete) {
// Bail out of the update by returning early
return;
}
// ...
}
);
#12296 2422df2 Thanks @Cellule! - Deprecate option ignoreResults in useMutation.
Once this option is removed, existing code still using it might see increase in re-renders.
If you don't want to synchronize your component state with the mutation, please use useApolloClient to get your ApolloClient instance and call client.mutate directly.
#12338 67c16c9 Thanks @phryneas! - In case of a multipart response (e.g. with @defer), query deduplication will
now keep going until the final chunk has been received.
#12276 670f112 Thanks @Cellule! - Fix the type of the variables property passed as the 2nd argument to the subscribeToMore updateQuery callback. This was previously reported as the variables type for the subscription itself, but is now properly typed as the query variables.
### Patch Changes - #12351 `3da908b` Thanks @jerelmiller! - Fixes an issue where the wrong networkStatus and loading value was emitted from observable
#12351 3da908b Thanks @jerelmiller! - Fixes an issue where the wrong networkStatus and loading value was emitted from observableQuery when calling fetchMore with a no-cache fetch policy. The networkStatus now properly reports as ready and loading as false after the result is returned.
#12354 a24ef94 Thanks @phryneas! - Fix missing main.d.cts file
### Patch Changes - #12341 `f2bb0b9` Thanks @phryneas! - useReadQuery/useQueryRefHandlers: Fix a "hook order" warning that might be emitted in React 1
``js const retryLink = new RetryLink({ attempts: (count, operation, error) => { if (error instanceof ApolloError) { // errors available on the protoco
#12321 daa4f33 Thanks @jerelmiller! - Fix type of extensions in protocolErrors for ApolloError and the onError link. According to the multipart HTTP subscription protocol, fatal tranport errors follow the GraphQL error format which require extensions to be a map as its value instead of an array.
#12318 b17968b Thanks @jerelmiller! - Allow RetryLink to retry an operation when fatal transport-level errors are emitted from multipart subscriptions.
const retryLink = new RetryLink({
attempts: (count, operation, error) => {
if (error instanceof ApolloError) {
// errors available on the `protocolErrors` field in `ApolloError`
console.log(error.protocolErrors);
}
return true;
},
});
### Patch Changes - #12292 `3abd944` Thanks @phryneas! - Remove unused dependency response-iterator - #12287 `bf313a3` Thanks @phryneas! - Fixes an is
`js const errorLink = onError(({ protocolErrors }) => { if (protocolErrors) { console.log(protocolErrors); } }); `
#12281 d638ec3 Thanks @jerelmiller! - Make fatal tranport-level errors from multipart subscriptions available to the error link with the protocolErrors property.
const errorLink = onError(({ protocolErrors }) => {
if (protocolErrors) {
console.log(protocolErrors);
}
});
#12281 d638ec3 Thanks @jerelmiller! - Fix the array type for the errors field on the ApolloPayloadResult type. This type was always in the shape of the GraphQL error format, per the multipart subscriptions protocol and never a plain string or a JavaScript error object.
### Patch Changes - #12267 `d57429d` Thanks @jerelmiller! - Maintain the TData type when used with Unmasked when TData is not a masked type generated
#12267 d57429d Thanks @jerelmiller! - Maintain the TData type when used with Unmasked when TData is not a masked type generated from GraphQL Codegen.
#12270 3601246 Thanks @jerelmiller! - Fix handling of tagged/branded primitive types when used as scalar values with Unmasked.
A new mode option has now been introduced to allow for the old behavior. See the next section on migrating if you wish to maintain the old default beh
#12252 cb9cd4e Thanks @jerelmiller! - Changes the default behavior of the MaybeMasked type to preserve types unless otherwise specified. This change makes it easier to upgrade from older versions of the client where types could have unexpectedly changed in the application due to the default of trying to unwrap types into unmasked types. This change also fixes the compilation performance regression experienced when simply upgrading the client since types are now preserved by default.
A new mode option has now been introduced to allow for the old behavior. See the next section on migrating if you wish to maintain the old default behavior after upgrading to this version.
If you've adopted data masking and have opted in to using masked types by setting the enabled property to true, you can remove this configuration entirely:
-declare module "@apollo/client" {
- interface DataMasking {
- mode: "unmask"
- }
-}
If you prefer to specify the behavior explicitly, change the property from enabled: true, to mode: "preserveTypes":
declare module "@apollo/client" {
interface DataMasking {
- enabled: true
+ mode: "preserveTypes"
}
}
If you rely on the default behavior in 3.12.4 or below and would like to continue to use unmasked types by default, set the mode to unmask:
declare module "@apollo/client" {
interface DataMasking {
mode: "unmask";
}
}
### Patch Changes - #12236 `4334d30` Thanks @charpeni! - Fix an issue with refetchQueries where comparing DocumentNodes internally by references could
### Patch Changes - #12214 `8bfee88` Thanks @phryneas! - Data masking: prevent infinite recursion of ContainsFragmentsRefs type - #12204 `851deb0` Tha
#12214 8bfee88 Thanks @phryneas! - Data masking: prevent infinite recursion of ContainsFragmentsRefs type
#12204 851deb0 Thanks @jerelmiller! - Fix Unmasked unwrapping tuple types into an array of their subtypes.
#12204 851deb0 Thanks @jerelmiller! - Ensure MaybeMasked does not try and unwrap types that contain index signatures.
#12204 851deb0 Thanks @jerelmiller! - Ensure MaybeMasked does not try to unwrap the type as Unmasked if the type contains any.
### Patch Changes - #12175 `84af347` Thanks @jerelmiller! - Update peer deps to allow for React 19 stable release.
84af347 Thanks @jerelmiller! - Update peer deps to allow for React 19 stable release.### Patch Changes - #12171 `e1efe74` Thanks @phryneas! - Fix import extension in masking entry point.
Data masking enforces that only the fields requested by the query or fragment is available to that component. Data masking is best paired with colocat
#12042 1c0ecbf Thanks @jerelmiller! - Introduces data masking in Apollo Client.
Data masking enforces that only the fields requested by the query or fragment is available to that component. Data masking is best paired with colocated fragments.
To enable data masking in Apollo Client, set the dataMasking option to true.
new ApolloClient({
dataMasking: true,
// ... other options
});
For detailed information on data masking, including how to incrementally adopt it in an existing applications, see the data masking documentation.
#12131 21c3f08 Thanks @jerelmiller! - Allow null as a valid from value in useFragment.
<details open> <summary><h3>More Patch Changes</h3></summary>
#12126 d10d702 Thanks @jerelmiller! - Maintain the existing document if its unchanged by the codemod and move to more naive whitespace formatting
#12150 9ed1e1e Thanks @jerelmiller! - Fix issue when using Unmasked with older versions of TypeScript when used with array fields.
#12116 8ae6e4e Thanks @jerelmiller! - Prevent field accessor warnings when using @unmask(mode: "migrate") on objects that are passed into cache.identify.
#12120 6a98e76 Thanks @jerelmiller! - Provide a codemod that applies @unmask to all named fragments for all operations and fragments.
Learn how to use the codemod in the incremental adoption documentation.
#12134 cfaf4ef Thanks @jerelmiller! - Fix issue where data went missing when an unmasked fragment in migrate mode selected fields that the parent did not.
#12154 d933def Thanks @phryneas! - Data masking types: handle overlapping nested array types and fragments on interface types.
#12139 5a53e15 Thanks @phryneas! - Fix issue where masked data would sometimes get returned when the field was part of a child fragment from a fragment unmasked by the parent query.
#12123 8422a30 Thanks @jerelmiller! - Warn when using data masking with "no-cache" operations.
#12139 5a53e15 Thanks @phryneas! - Fix issue where the warning emitted by @unmask(mode: "migrate") would trigger unnecessarily when the fragment was used alongside a masked fragment inside an inline fragment.
#12114 1d4ce00 Thanks @jerelmiller! - Fix error when combining @unmask and @defer directives on a fragment spread when data masking is enabled.
#12130 1e7d009 Thanks @jerelmiller! - Fix error thrown when applying unmask migrate mode warnings on interface types with selection sets that contain inline fragment conditions.
#12152 78137ec Thanks @phryneas! - Add a helper that will skip the TS unmasking alorithm when no fragments are present on type level
#12126 d10d702 Thanks @jerelmiller! - Ensure documents unchanged by the codemod are left untouched.
#12133 a6ece37 Thanks @jerelmiller! - Ensure null is retained in nullable types when unmasking a type with the Unmasked helper type.
#12139 5a53e15 Thanks @phryneas! - Fix issue that threw errors when masking partial data with @unmask(mode: "migrate").
</details>
### Patch Changes - #12154 `d933def` Thanks @phryneas! - Data masking types: handle overlapping nested array types and fragments on interface types.
### Patch Changes - #12150 `9ed1e1e` Thanks @jerelmiller! - Fix issue when using Unmasked with older versions of TypeScript when used with array field
### Patch Changes - #12139 `5a53e15` Thanks @phryneas! - Fix issue where masked data would sometimes get returned when the field was part of a child f
#12139 5a53e15 Thanks @phryneas! - Fix issue where masked data would sometimes get returned when the field was part of a child fragment from a fragment unmasked by the parent query.
#12139 5a53e15 Thanks @phryneas! - Fix issue where the warning emitted by @unmask(mode: "migrate") would trigger unnecessarily when the fragment was used alongside a masked fragment inside an inline fragment.
#12139 5a53e15 Thanks @phryneas! - Fix issue that threw errors when masking partial data with @unmask(mode: "migrate").
### Minor Changes - #12131 `21c3f08` Thanks @jerelmiller! - Allow null as a valid from value in useFragment. ### Patch Changes - #12126 `d10d702` Than
21c3f08 Thanks @jerelmiller! - Allow null as a valid from value in useFragment.#12126 d10d702 Thanks @jerelmiller! - Maintain the existing document if its unchanged by the codemod and move to more naive whitespace formatting
#12134 cfaf4ef Thanks @jerelmiller! - Fix issue where data went missing when an unmasked fragment in migrate mode selected fields that the parent did not.
#12130 1e7d009 Thanks @jerelmiller! - Fix error thrown when applying unmask migrate mode warnings on interface types with selection sets that contain inline fragment conditions.
#12126 d10d702 Thanks @jerelmiller! - Ensure documents unchanged by the codemod are left untouched.
#12133 a6ece37 Thanks @jerelmiller! - Ensure null is retained in nullable types when unmasking a type with the Unmasked helper type.
npx jscodeshift -t node_modules/@apollo/client/scripts/codemods/data-masking/unmask.ts --extensions tsx --parser tsx path/to/app/
#12116 8ae6e4e Thanks @jerelmiller! - Prevent field accessor warnings when using @unmask(mode: "migrate") on objects that are passed into cache.identify.
#12120 6a98e76 Thanks @jerelmiller! - Provide a codemod that applies @unmask to all named fragments for all operations and fragments. To use the codemod, run the following command:
npx jscodeshift -t node_modules/@apollo/client/scripts/codemods/data-masking/unmask.ts --extensions tsx --parser tsx path/to/app/
To customize the tag used to search for GraphQL operations, use the --tag option. By default the codemod looks for gql and graphql tags.
To apply the directive in migrate mode in order to receive runtime warnings on potentially masked fields, use the --mode migrate option.
For more information on the options that can be used with jscodeshift, check out the jscodeshift documentation.
#12121 1085a95 Thanks @jerelmiller! - Warn when using data masking with "no-cache" operations.
#12114 1d4ce00 Thanks @jerelmiller! - Fix error when combining @unmask and @defer directives on a fragment spread when data masking is enabled.
To enable data masking in Apollo Client, set the dataMasking option to true.
#12042 1c0ecbf Thanks @jerelmiller! - Introduces data masking into Apollo Client. Data masking allows components to access only the data they asked for through GraphQL fragments. This prevents coupling between components that might otherwise implicitly rely on fields not requested by the component. Data masking also provides the benefit that masked fields only rerender components that ask for the field.
To enable data masking in Apollo Client, set the dataMasking option to true.
new ApolloClient({
dataMasking: true,
// ... other options
});
You can selectively disable data masking using the @unmask directive. Apply this to any named fragment to receive all fields requested by the fragment.
query {
user {
id
...UserFields @unmask
}
}
To help with migration, use the @unmask migrate mode which will add warnings when accessing fields that would otherwise be masked.
query {
user {
id
...UserFields @unmask(mode: "migrate")
}
}
Nothing published for this version
### Patch Changes - #12093 `1765668` Thanks @mgmolisani! - Fixed a bug when evaluating the devtools flag with the new syntax devtools.enabled that cou
1765668 Thanks @mgmolisani! - Fixed a bug when evaluating the devtools flag with the new syntax devtools.enabled that could result to true when explicitly set to false.### Patch Changes - #12110 `a3f95c6` Thanks @jerelmiller! - Fix an issue where errors returned from a fetchMore call from a Suspense hook would cause
a3f95c6 Thanks @jerelmiller! - Fix an issue where errors returned from a fetchMore call from a Suspense hook would cause a Suspense boundary to be shown indefinitely.### Patch Changes - #12054 `35cf186` Thanks @phryneas! - Fixed a bug where incorrect object access in some Safari extensions could cause a crash.
### Patch Changes - #12052 `e471cef` Thanks @jerelmiller! - Fixes a regression from where passing an invalid identifier to from in useFragment would r
e471cef Thanks @jerelmiller! - Fixes a regression from where passing an invalid identifier to from in useFragment would result in the warning TypeError: Cannot read properties of undefined (reading '__typename').### Patch Changes - #12049 `9c26892` Thanks @phryneas and @maciesielka! - Fix a bug where useFragment did not re-render as expected - #12044 `04462a2`
#12049 9c26892 Thanks @phryneas and @maciesielka! - Fix a bug where useFragment did not re-render as expected
#12044 04462a2 Thanks @DoctorJohn! - Cache the useSubscription hook's restart function definition between re-renders.
### Patch Changes - #12027 `eb3e21b` Thanks @JavaScriptBach! - Type MutationResult.reset as an arrow function - #12020 `82d8cb4` Thanks @jerelmiller!
#12027 eb3e21b Thanks @JavaScriptBach! - Type MutationResult.reset as an arrow function
#12020 82d8cb4 Thanks @jerelmiller! - Better conform to Rules of React by avoiding write of ref in render for useFragment.
Previously, calling client.clearStore() while a query was running had one of these results:
#11994 41b17e5 Thanks @jerelmiller! - Update the Modifier function type to allow cache.modify to return deeply partial data.
#11989 e609156 Thanks @phryneas! - Fix a potential crash when calling clearStore while a query was running.
Previously, calling client.clearStore() while a query was running had one of these results:
useQuery would stay in a loading: true state.useLazyQuery would stay in a loading: true state, but also crash with a "Cannot read property 'data' of undefined" error.Now, in both cases, the hook will enter an error state with a networkError, and the promise returned by the useLazyQuery execute function will return a result in an error state.
#11994 41b17e5 Thanks @jerelmiller! - Prevent accidental distribution on cache.modify field modifiers when a field is a union type array.
When calling fetchMore with a query that has a no-cache fetch policy, fetchMore will now throw if an updateQuery function is not provided. This provid
#11984 5db1659 Thanks @jerelmiller! - Fix an issue where multiple fetches with results that returned errors would sometimes set the data property with an errorPolicy of none.
#11974 c95848e Thanks @jerelmiller! - Fix an issue where fetchMore would write its result data to the cache when using it with a no-cache fetch policy.
#11974 c95848e Thanks @jerelmiller! - Fix an issue where executing fetchMore with a no-cache fetch policy could sometimes result in multiple network requests.
#11974 c95848e Thanks @jerelmiller! -
When calling fetchMore with a query that has a no-cache fetch policy, fetchMore will now throw if an updateQuery function is not provided. This provides a mechanism to merge the results from the fetchMore call with the query's previous result.
### Patch Changes - #11980 `38c0a2c` Thanks @jerelmiller! - Fix missing getServerSnapshot error when using useSubscription on the server.
38c0a2c Thanks @jerelmiller! - Fix missing getServerSnapshot error when using useSubscription on the server.### Patch Changes - #11969 `061cab6` Thanks @jerelmiller! - Remove check for window.__APOLLO_CLIENT__ when determining whether to connect to Apollo Cl
#11969 061cab6 Thanks @jerelmiller! - Remove check for window.__APOLLO_CLIENT__ when determining whether to connect to Apollo Client Devtools when connectToDevtools or devtools.enabled is not specified. This now simply checks to see if the application is in development mode.
#11971 ecf77f6 Thanks @jerelmiller! - Prevent the setTimeout for suggesting devtools from running in non-browser environments.
This was a type bug - these errors were never GraphQLError instances to begin with, and the GraphQLError class has additional properties that can neve
#11789 5793301 Thanks @phryneas! - Changes usages of the GraphQLError type to GraphQLFormattedError.
This was a type bug - these errors were never GraphQLError instances
to begin with, and the GraphQLError class has additional properties that can
never be correctly rehydrated from a GraphQL result.
The correct type to use here is GraphQLFormattedError.
Similarly, please ensure to use the type FormattedExecutionResult
instead of ExecutionResult - the non-"Formatted" versions of these types
are for use on the server only, but don't get transported over the network.
#11626 228429a Thanks @phryneas! - Call nextFetchPolicy with "variables-changed" even if there is a fetchPolicy specified.
Previously this would only be called when the current fetchPolicy was equal to the fetchPolicy option or the option was not specified. If you use nextFetchPolicy as a function, expect to see this function called more often.
Due to this bug, this also meant that the fetchPolicy might be reset to the initial fetchPolicy, even when you specified a nextFetchPolicy function. If you previously relied on this behavior, you will need to update your nextFetchPolicy callback function to implement this resetting behavior.
As an example, if your code looked like the following:
useQuery(QUERY, {
nextFetchPolicy(currentFetchPolicy, info) {
// your logic here
}
);
Update your function to the following to reimplement the resetting behavior:
useQuery(QUERY, {
nextFetchPolicy(currentFetchPolicy, info) {
if (info.reason === 'variables-changed') {
return info.initialFetchPolicy;
}
// your logic here
}
);
#11923 d88c7f8 Thanks @jerelmiller! - Add support for subscribeToMore function to useQueryRefHandlers.
#11854 3812800 Thanks @jcostello-atlassian! - Support extensions in useSubscription
#11923 d88c7f8 Thanks @jerelmiller! - Add support for subscribeToMore function to useLoadableQuery.
#11863 98e44f7 Thanks @phryneas! - Reimplement useSubscription to fix rules of React violations.
#11869 a69327c Thanks @phryneas! - Rewrite big parts of useQuery and useLazyQuery to be more compliant with the Rules of React and React Compiler
#11936 1b23337 Thanks @jerelmiller! - Add the ability to specify a name for the client instance for use with Apollo Client Devtools. This is useful when instantiating multiple clients to identify the client instance more easily. This deprecates the connectToDevtools option in favor of a new devtools configuration.
new ApolloClient({
devtools: {
enabled: true,
name: "Test Client",
},
});
This option is backwards-compatible with connectToDevtools and will be used in the absense of a devtools option.
#11923 d88c7f8 Thanks @jerelmiller! - Add support for subscribeToMore function to useBackgroundQuery.
#11930 a768575 Thanks @jerelmiller! - Deprecates experimental schema testing utilities introduced in 3.10 in favor of recommending @apollo/graphql-testing-library.
#11951 0de03af Thanks @phryneas! - add React 19 RC to peerDependencies
#11927 2941824 Thanks @phryneas! - Add restart function to useSubscription.
#11949 4528918 Thanks @alessbell! - Remove deprecated watchFragment option, canonizeResults
#11937 78332be Thanks @phryneas! - createSchemaFetch: simulate serialized errors instead of an ApolloError instance
#11902 96422ce Thanks @phryneas! - Add cause field to ApolloError.
#11806 8df6013 Thanks @phryneas! - MockLink: add query default variables if not specified in mock request
#11926 3dd6432 Thanks @phryneas! - watchFragment: forward additional options to diffOptions
#11946 7d833b8 Thanks @jerelmiller! - Fix issue where mutations were not accessible by Apollo Client Devtools in 3.11.0-rc.0.
#11944 8f3d7eb Thanks @sneyderdev! - Allow IgnoreModifier to be returned from a optimisticResponse function when inferring from a TypedDocumentNode when used with a generic argument.
#11954 4a6e86a Thanks @phryneas! - Document (and deprecate) the previously undocumented errors property on the useQuery QueryResult type.
#11719 09a6677 Thanks @phryneas! - Allow wrapping createQueryPreloader
#11921 70406bf Thanks @phryneas! - add ignoreResults option to useSubscription
### Patch Changes - #11951 `0de03af` Thanks @phryneas! - add React 19 RC to peerDependencies - #11937 `78332be` Thanks @phryneas! - createSchemaFetch:
#11951 0de03af Thanks @phryneas! - add React 19 RC to peerDependencies
#11937 78332be Thanks @phryneas! - createSchemaFetch: simulate serialized errors instead of an ApolloError instance
#11944 8f3d7eb Thanks @sneyderdev! - Allow IgnoreModifier to be returned from a optimisticResponse function when inferring from a TypedDocumentNode when used with a generic argument.
#11954 4a6e86a Thanks @phryneas! - Document (and deprecate) the previously undocumented errors property on the useQuery QueryResult type.
### Patch Changes - #11949 `4528918` Thanks @alessbell! - Remove deprecated watchFragment option, canonizeResults - #11926 `3dd6432` Thanks @phryneas!
#11949 4528918 Thanks @alessbell! - Remove deprecated watchFragment option, canonizeResults
#11926 3dd6432 Thanks @phryneas! - watchFragment: forward additional options to diffOptions
#11946 7d833b8 Thanks @jerelmiller! - Fix issue where mutations were not accessible by Apollo Client Devtools in 3.11.0-rc.0.
`ts new ApolloClient({ devtools: { enabled: true, name: "Test Client", }, }); `
#11923 d88c7f8 Thanks @jerelmiller! - Add support for subscribeToMore function to useQueryRefHandlers.
#11854 3812800 Thanks @jcostello-atlassian! - Support extensions in useSubscription
#11923 d88c7f8 Thanks @jerelmiller! - Add support for subscribeToMore function to useLoadableQuery.
#11863 98e44f7 Thanks @phryneas! - Reimplement useSubscription to fix rules of React violations.
#11869 a69327c Thanks @phryneas! - Rewrite big parts of useQuery and useLazyQuery to be more compliant with the Rules of React and React Compiler
#11936 1b23337 Thanks @jerelmiller! - Add the ability to specify a name for the client instance for use with Apollo Client Devtools. This is useful when instantiating multiple clients to identify the client instance more easily. This deprecates the connectToDevtools option in favor of a new devtools configuration.
new ApolloClient({
devtools: {
enabled: true,
name: "Test Client",
},
});
This option is backwards-compatible with connectToDevtools and will be used in the absense of a devtools option.
#11923 d88c7f8 Thanks @jerelmiller! - Add support for subscribeToMore function to useBackgroundQuery.
#11789 5793301 Thanks @phryneas! - Changes usages of the GraphQLError type to GraphQLFormattedError.
This was a type bug - these errors were never GraphQLError instances
to begin with, and the GraphQLError class has additional properties that can
never be correctly rehydrated from a GraphQL result.
The correct type to use here is GraphQLFormattedError.
Similarly, please ensure to use the type FormattedExecutionResult
instead of ExecutionResult - the non-"Formatted" versions of these types
are for use on the server only, but don't get transported over the network.
#11930 a768575 Thanks @jerelmiller! - Deprecates experimental schema testing utilities introduced in 3.10 in favor of recommending @apollo/graphql-testing-library.
#11927 2941824 Thanks @phryneas! - Add restart function to useSubscription.
#11902 96422ce Thanks @phryneas! - Add cause field to ApolloError.
#11806 8df6013 Thanks @phryneas! - MockLink: add query default variables if not specified in mock request
#11626 228429a Thanks @phryneas! - Call nextFetchPolicy with "variables-changed" even if there is a fetchPolicy specified. (fixes #11365)
#11719 09a6677 Thanks @phryneas! - Allow wrapping createQueryPreloader
#11921 70406bf Thanks @phryneas! - add ignoreResults option to useSubscription
### Patch Changes - #11911 `1f0460a` Thanks @jerelmiller! - Allow undefined to be returned from a cache.modify modifier function when a generic type a
1f0460a Thanks @jerelmiller! - Allow undefined to be returned from a cache.modify modifier function when a generic type argument is used.### Patch Changes - #11901 `10a8c0a` Thanks @phryneas! - update canUseLayoutEffect check to also allow for layout effects in React Native - #11861 `1a
#11901 10a8c0a Thanks @phryneas! - update canUseLayoutEffect check to also allow for layout effects in React Native
#11861 1aed0e8 Thanks @henryqdineen! - Defend against non-serializable params in invariantWrappers
#11905 29755da Thanks @phryneas! - Add .d.cts files for cjs bundles
#11906 d104759 Thanks @phryneas! - chore: update TypeScript to 5.5
### Patch Changes - #11900 `f745558` Thanks @phryneas! - useMutation: use useIsomorphicLayoutEffect instead of useLayoutEffect
### Patch Changes - #11888 `7fb7939` Thanks @phryneas! - switch useRenderGuard to an approach not accessing React's internals - #11511 `6536369` Thank
#11888 7fb7939 Thanks @phryneas! - switch useRenderGuard to an approach not accessing React's internals
#11511 6536369 Thanks @phryneas! - useLoadableQuery: ensure that loadQuery is updated if the ApolloClient instance changes
#11860 8740f19 Thanks @alessbell! - Fixes #11849 by reevaluating window.fetch each time BatchHttpLink uses it, if not configured via options.fetch. Takes the same approach as PR #8603 which fixed the same issue in HttpLink.
#11852 d502a69 Thanks @phryneas! - Fix a bug where calling the useMutation reset function would point the hook to an outdated client reference.
#11329 3d164ea Thanks @PaLy! - Fix graphQLErrors in Error Link if networkError.result is an empty string
#11852 d502a69 Thanks @phryneas! - Prevent writing to a ref in render in useMutation.
As a result, you might encounter problems in the future if you call the mutation's execute function during render. Please note that this was never supported behavior, and we strongly recommend against it.
#11848 ad63924 Thanks @phryneas! - Ensure covariant behavior: MockedResponse<X,Y> should be assignable to MockedResponse
#11851 45c47be Thanks @phryneas! - Avoid usage of useRef in useInternalState to prevent ref access in render.
#11877 634d91a Thanks @phryneas! - Add missing name to tuple member (fix TS5084)
#11851 45c47be Thanks @phryneas! - Fix a bug where useLazyQuery would not pick up a client change.
While we tend to avoid any types of breaking changes in patch releases as this, this change was necessary to support an upcoming version of the React…
#11838 8475346 Thanks @alex-kinokon! - Don’t prompt for DevTools installation for browser extension page
#11839 6481fe1 Thanks @jerelmiller! - Fix a regression in 3.9.5 where a merge function that returned an incomplete result would not allow the client to refetch in order to fulfill the query.
#11844 86984f2 Thanks @jerelmiller! - Honor the @nonreactive directive when using cache.watchFragment or the useFragment hook to avoid rerendering when using these directives.
#11824 47ad806 Thanks @phryneas! - Create branded QueryRef type without exposed properties.
This change deprecates QueryReference in favor of a QueryRef type that doesn't expose any properties.
This change also updates preloadQuery to return a new PreloadedQueryRef type, which exposes the toPromise function as it does today. This means that query refs produced by useBackgroundQuery and useLoadableQuery now return QueryRef types that do not have access to a toPromise function, which was never meant to be used in combination with these hooks.
While we tend to avoid any types of breaking changes in patch releases as this, this change was necessary to support an upcoming version of the React Server Component integration, which needed to omit the toPromise function that would otherwise have broken at runtime.
Note that this is a TypeScript-only change. At runtime, toPromise is still present on all queryRefs currently created by this package - but we strongly want to discourage you from accessing it in all cases except for the PreloadedQueryRef use case.
Migration is as simple as replacing all references to QueryReference with QueryRef, so it should be possible to do this with a search & replace in most code bases:
-import { QueryReference } from '@apollo/client'
+import { QueryRef } from '@apollo/client'
- function Component({ queryRef }: { queryRef: QueryReference<TData> }) {
+ function Component({ queryRef }: { queryRef: QueryRef<TData> }) {
// ...
}
#11845 4c5c820 Thanks @jerelmiller! - Remove @nonreactive directives from queries passed to MockLink to ensure they are properly matched.
#11837 dff15b1 Thanks @jerelmiller! - Fix an issue where a polled query created in React strict mode may not stop polling after the component unmounts while using the cache-and-network fetch policy.
### Patch Changes - #11811 `d67d7f9` Thanks @phryneas! - Adjust some types for React 19 compat - #11834 `7d8aad4` Thanks @psamim! - Fix error "Cannot
### Patch Changes - #11821 `2675d3c` Thanks @jerelmiller! - Fix a regression where rerendering a component with useBackgroundQuery would recreate the
#11821 2675d3c Thanks @jerelmiller! - Fix a regression where rerendering a component with useBackgroundQuery would recreate the queryRef instance when used with React's strict mode.
#11821 2675d3c Thanks @jerelmiller! - Revert the change introduced in
3.9.10 via #11738 that disposed of queryRefs synchronously. This change caused too many issues with strict mode.
### Patch Changes - #11792 `5876c35` Thanks @phryneas! - AutoCleanedCache: only schedule batched cache cleanup if the cache is full (fixes #11790) - #
#11792 5876c35 Thanks @phryneas! - AutoCleanedCache: only schedule batched cache cleanup if the cache is full (fixes #11790)
#11799 1aca7ed Thanks @phryneas! - RenderPromises: use canonicalStringify to serialize variables to ensure query deduplication is properly applied even when variables are specified in a different order.
#11803 bf9dd17 Thanks @phryneas! - Update the rehackt dependency to ^0.1.0
#11756 60592e9 Thanks @henryqdineen! - Fix operation.setContext() type
### Minor Changes - #11605 `e2dd4c9` Thanks @alessbell! - Adds createMockFetch utility for integration testing that includes the link chain - #11760 `
#11605 e2dd4c9 Thanks @alessbell! - Adds createMockFetch utility for integration testing that includes the link chain
#11760 acd1982 Thanks @alessbell! - createTestSchema now uses graphql-tools mergeResolvers to merge resolvers instead of a shallow merge.
#11764 f046aa9 Thanks @alessbell! - Rename createProxiedSchema to createTestSchema and createMockFetch to createSchemaFetch.
#11777 5dfc79f Thanks @alessbell! - Call createMockSchema inside createTestSchema.
#11774 2583488 Thanks @alessbell! - Add ability to set min and max delay in createSchemaFetch
#11605 e2dd4c9 Thanks @alessbell! - Adds proxiedSchema and createMockSchema testing utilities
#11465 7623da7 Thanks @alessbell! - Add watchFragment method to the cache and expose it on ApolloClient, refactor useFragment using watchFragment.
#11743 78891f9 Thanks @jerelmiller! - Remove alpha designation for queryRef.toPromise() to stabilize the API.
#11743 78891f9 Thanks @jerelmiller! - Remove alpha designation for createQueryPreloader to stabilize the API.
#11783 440563a Thanks @alessbell! - Moves new testing utilities to their own entrypoint, testing/experimental
#11757 9825295 Thanks @phryneas! - Adjust useReadQuery wrapper logic to work with transported objects.
#11771 e72cbba Thanks @phryneas! - Wrap useQueryRefHandlers in wrapHook.
#11754 80d2ba5 Thanks @alessbell! - Export WatchFragmentOptions and WatchFragmentResult from main entrypoint and fix bug where this wasn't bound to the watchFragment method on ApolloClient.
Your coding agent can read these notes before it upgrades. Set up the MCP server →