UNPKG

@apollo/client

Version:

A fully-featured caching GraphQL client.

785 lines (532 loc) 683 kB
# @apollo/client ## 4.0.0 # Apollo Client 4.0 Release Notes Apollo Client 4.0 delivers a more modern, efficient, and type-safe GraphQL client experience through various architectural improvements and API refinements. This release focuses on developer experience, bundle size optimization, and framework flexibility. ## Key Improvements ### 🎯 Framework-Agnostic Core Apollo Client 4.0 separates React functionality from the core library, making `@apollo/client` truly framework-agnostic. React exports now live in `@apollo/client/react`, allowing developers to use Apollo Client with any JavaScript framework without React dependencies. ### 📦 Smaller Bundle Sizes - **Opt-in Local State Management**: The `@client` directive functionality is now opt-in via the `LocalState` class, reducing bundle size when not using local state - **Modern Build Target**: Transpiled to target `since 2023, node >= 20, not dead`, leveraging modern JavaScript features for better performance - **Improved Tree-Shaking**: Proper `exports` field in package.json enables better dead code elimination ### 💥 Unified Error Handling Apollo Client 4.0 completely reimagines error handling for better clarity and debugging: - `ApolloError` removed in favor of specific error classes - Unification of errors to a single `error` property - Network errors now respect `errorPolicy` settings - External errors passed through without wrapping - New, more granular error classes with static `.is()` methods for robust type narrowing ### 🔧 Enhanced TypeScript Support - **Namespaced Types**: Types are now colocated with their APIs (e.g., `useQuery.Options` instead of `QueryHookOptions`) - **Precise Return Types**: Return types accurately reflect the options passed (e.g., `returnPartialData` makes `data` type `DeepPartial<TData>`) - **Stricter Type Safety**: Required variables are now enforced more consistently throughout the client - **New `dataState` Property**: Enables accurate type narrowing of query results - **Module Augmentation**: Custom context types via declaration merging instead of fragile generics - **Customizable Type Implementations**: Select types can now be customized to provide your own type implementation to seamlessly integrate with external tools such as GraphQL Codegen or `gql.tada` ### ⚡ Modern Observable Implementation Apollo Client 4.0 migrates from `zen-observable` to **RxJS**, providing the industry-standard Observable implementation backed by a rich ecosystem of utilities. ## Major Features ### Unified Error Handling Apollo Client 4.0 completely reimagines error handling for better clarity and debugging: **Key Changes:** - `ApolloError` removed in favor of specific error classes - Network errors now respect `errorPolicy` settings - External errors passed through without wrapping - New error classes with static `.is()` methods for type checking **Error Classes:** - `CombinedGraphQLErrors` - GraphQL errors from the server - `ServerError` - Non-GraphQL server errors - `ServerParseError` - Server response parsing errors - `UnconventionalError` - Wrapper for non-error thrown values - `LinkError` - Errors from the link chain (via `.is()` check) **Migration Example:** ```typescript // Apollo Client 3 if (error instanceof ApolloError) { console.log(error.graphQLErrors); console.log(error.networkError); } // Apollo Client 4 import { CombinedGraphQLErrors } from "@apollo/client"; if (CombinedGraphQLErrors.is(error)) { console.log(error.errors); // GraphQL errors } else if (error) { console.log(error.message); // Other errors } ``` ### The `dataState` Property A new property that clearly indicates the completeness of query results: **Values:** - `empty` - No data available (`data` is `undefined`) - `partial` - Incomplete data from cache when `returnPartialData` is `true` - `streaming` - Incomplete data from a deferred query still streaming - `complete` - Fully satisfied query result **Benefits:** - Accurate TypeScript type narrowing - Clear loading state distinction - Better handling of partial results ```typescript const { data, dataState } = useQuery(MY_QUERY); if (dataState === "complete") { // TypeScript knows data is fully populated console.log(data.allFields); } else if (dataState === "partial") { // TypeScript knows data might be missing fields console.log(data?.someField); } ``` ### Pluggable Incremental Delivery (`@defer` Support) Apollo Client 4.0 makes incremental delivery configurable and future-proof: ```typescript import { Defer20220824Handler } from "@apollo/client/incremental"; const client = new ApolloClient({ // ... incrementalHandler: new Defer20220824Handler(), }); ``` **Available Handlers:** - `NotImplementedHandler` - Default, throws if `@defer` is used - `Defer20220824Handler` - Apollo Router format support (also aliased as `GraphQL17Alpha2Handler`) ### Local State Management Improvements Local state is now opt-in via the `LocalState` class: ```typescript import { LocalState } from "@apollo/client/local-state"; const client = new ApolloClient({ cache, localState: new LocalState({ resolvers: { Query: { myField: () => "Hello World", }, }, }), }); ``` **Resolver Context Changes:** ```typescript // Apollo Client 3 const resolver = (parent, args, context, info) => { const { cache } = context; }; // Apollo Client 4 const resolver = (parent, args, context, info) => { const { client, requestContext, phase } = context; const cache = client.cache; }; ``` ## React-Specific Improvements ### More Predictable Hooks **`useLazyQuery` Overhaul:** - No longer accepts `variables` or `context` options (pass to `execute` instead) - `execute` function only accepts `variables` and `context` - Cannot be called during render or SSR - Automatic cancellation of in-flight queries when new ones start **`useMutation` Changes:** - Removed `ignoreResults` option - use `client.mutate` directly for fire-and-forget mutations **`useQuery` Changes:** - `notifyOnNetworkStatusChange` now defaults to `true` - Removed deprecated `onCompleted` and `onError` callbacks ### New SSR API The new `prerenderStatic` API replaces deprecated SSR functions: ```typescript import { prerenderStatic } from "@apollo/client/react/ssr"; // Works with React 19's prerender APIs const html = await prerenderStatic(<App />, { client, }); ``` ### React Compiler Support Pre-compiled React hooks optimized by the React Compiler: ```typescript // Use compiled hooks for potential performance improvements import { useQuery } from "@apollo/client/react/compiled"; ``` The compiled hooks are built with React Compiler v19.1.0-rc.2 and include a runtime polyfill for compatibility with React 17+. ## Link System Evolution ### All Links Now Classes Migration from creator functions to classes: ```typescript // Apollo Client 3 import { createHttpLink, setContext } from "@apollo/client"; const httpLink = createHttpLink({ uri: "/graphql" }); const authLink = setContext((operation, prevContext) => { /*...*/ }); // Apollo Client 4 import { HttpLink, SetContextLink } from "@apollo/client"; const httpLink = new HttpLink({ uri: "/graphql" }); const authLink = new SetContextLink((prevContext, operation) => { /*...*/ }); ``` ### ErrorLink Changes ```typescript // Apollo Client 3 onError(({ graphQLErrors, networkError }) => { // Handle errors separately }); // Apollo Client 4 new ErrorLink(({ error }) => { if (CombinedGraphQLErrors.is(error)) { // Handle GraphQL errors } else if (error) { // Handle other errors } }); ``` ## Migration Tools ### Automated Codemod Apollo Client 4.0 provides a comprehensive codemod to automate migration: ```bash # Basic usage npx apollo-client-codemod-migrate-3-to-4 src # TypeScript projects (run separately) npx apollo-client-codemod-migrate-3-to-4 --parser ts --extensions ts src npx apollo-client-codemod-migrate-3-to-4 --parser tsx --extensions tsx src ``` The codemod handles: 1. **Import updates** - Moves React imports to `@apollo/client/react` 2. **Type migrations** - Updates types to new namespaced locations 3. **Link updates** - Converts creator functions to classes 4. **Removed exports** - Moves to `@apollo/client/v4-migration` with migration instructions ## Breaking Changes Summary ### Installation ```bash # RxJS is now a peer dependency npm install @apollo/client graphql rxjs ``` ### ApolloClient Constructor - `link` option is now required (no more implicit `HttpLink` creation) - `uri`, `headers`, `credentials` removed - use `HttpLink` directly - `name` and `version` moved to `clientAwareness` option - `resolvers` moved to `LocalState` constructor - `connectToDevTools` replaced with `devtools.enabled` - `disableNetworkFetches` renamed to `prioritizeCacheValues` ### Type System - Removed `TContext` and `TCacheShape` generics - Types moved to namespaces (see migration guide for full list) - Custom context via module augmentation ### Observable Changes - Requires calling `.pipe()` for transformations - Use RxJS operators instead of method chaining ### Testing - `MockedProvider` now has realistic delays by default (20-50ms) - `createMockClient` removed - use `MockLink` directly ## Performance & Build Improvements - **Modern JavaScript**: No downlevel transpilation for modern features - **No Polyfills**: Cleaner bundles, bring your own if needed - **Development Mode**: Controlled via export conditions, not global `__DEV__` - **ESM Support**: Proper `exports` field for better module resolution - **Source Maps**: Fixed and improved for better debugging ## Deprecations & Removals ### Removed Packages/Exports - React render prop components (`@apollo/client/react/components`) - Higher-order components (`@apollo/client/react/hoc`) - `@apollo/client/react/parser` - `@apollo/client/utilities/globals` ## Upgrade Path 1. **Update to Apollo Client 3.14** first for deprecation warnings 2. **Install peer dependencies**: `npm install rxjs` 3. **Run the codemod** to automate import and type updates 4. **Update ApolloClient initialization** (explicit `HttpLink`, `LocalState` if needed) 5. **Review error handling** - update to use new error classes 6. **Test thoroughly** - especially SSR, error handling, and local state ## Resources - [Migration Guide](https://www.apollographql.com/docs/react/migrating/apollo-client-4-migration) - [Changelog](https://github.com/apollographql/apollo-client/blob/main/CHANGELOG.md) ## Acknowledgments Apollo Client 4.0 represents years of community feedback and contributions. Thank you to all our contributors, early adopters, and the entire GraphQL community for making this release possible. <details> <summary> ### Major Changes </summary> - [#12644](https://github.com/apollographql/apollo-client/pull/12644) [`fe2f005`](https://github.com/apollographql/apollo-client/commit/fe2f005c34913ae082b96a807dc240e2785d50bd) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Replace the `result` property on `ServerError` with `bodyText`. `bodyText` is set to the raw string body. `HttpLink` and `BatchHttpLink` no longer try and parse the response body as JSON when a `ServerError` is thrown. - [#12673](https://github.com/apollographql/apollo-client/pull/12673) [`cee90ab`](https://github.com/apollographql/apollo-client/commit/cee90abcd2a9c91c5fdf872cf2d1c12deaa6593e) Thanks [@phryneas](https://github.com/phryneas)! - The `includeExtensions` option of `HttpLink` and `BatchHttpLink` now defaults to `true`. If `includeExtensions` is `true`, but `extensions` is not set or empty, extensions will not be included in outgoing requests. - [#12686](https://github.com/apollographql/apollo-client/pull/12686) [`dc4b1d0`](https://github.com/apollographql/apollo-client/commit/dc4b1d0d2479a37067113b7bd161a550fb8e4df6) Thanks [@jerelmiller](https://github.com/jerelmiller)! - A `@defer` query that has not yet finished streaming is now considered loading and thus the `loading` flag will be `true` until the response has completed. A new `NetworkStatus.streaming` value has been introduced and will be set as the `networkStatus` while the response is streaming. - [#12539](https://github.com/apollographql/apollo-client/pull/12539) [`dd0d6d6`](https://github.com/apollographql/apollo-client/commit/dd0d6d6d96d8b810e30dc2fdee2ac8a2477d0017) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `onError` link now uses a single `error` property to report the error that caused the link callback to be called. This will be an instance of `CombinedGraphQLErrors` in the event GraphQL errors were emitted from the terminating link, `CombinedProtocolErrors` if the terminating link emitted protocol errors, or the unwrapped error type if any other non-GraphQL error was thrown or emitted. ```diff - const errorLink = onError(({ graphQLErrors, networkError, protocolErrors }) => { - graphQLErrors.forEach(error => console.log(error.message)); + const errorLink = onError(({ error }) => { + if (error.name === 'CombinedGraphQLErrors') { + error.errors.forEach(rawError => console.log(rawError.message)); + } }); ``` - [#12586](https://github.com/apollographql/apollo-client/pull/12586) [`605db8e`](https://github.com/apollographql/apollo-client/commit/605db8e94fe2ce74c0a395f38f6873d40f431365) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the `typeDefs` option from `ApolloClient`. - [#12384](https://github.com/apollographql/apollo-client/pull/12384) [`6aa6fd3`](https://github.com/apollographql/apollo-client/commit/6aa6fd316cfdb31ebbe3e3133cca2965604e7ca1) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the `asyncMap` utility function. Instead use one of the RxJS operators that creates Observables from promises, such as `from`. - [#12398](https://github.com/apollographql/apollo-client/pull/12398) [`8cf5077`](https://github.com/apollographql/apollo-client/commit/8cf5077bed1ab46fdd32c5e253071506c0076064) Thanks [@jerelmiller](https://github.com/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](https://github.com/apollographql/apollo-client/pull/12379) [`ef892b4`](https://github.com/apollographql/apollo-client/commit/ef892b4dc505b02049525f9aba32c51f1c00c922) Thanks [@jerelmiller](https://github.com/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](https://github.com/apollographql/apollo-client/pull/12396) [`00f3d0a`](https://github.com/apollographql/apollo-client/commit/00f3d0a674eede1f909092283041cf8ac8d1b576) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the deprecated `errors` property from `useQuery` and `useLazyQuery`. Read errors from the `error` property instead. - [#12809](https://github.com/apollographql/apollo-client/pull/12809) [`e2a0be8`](https://github.com/apollographql/apollo-client/commit/e2a0be8c3f8b242706f90e0dcc022628992a8ae8) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `operation.getContext` now returns a `Readonly<OperationContext>` type. - [#12809](https://github.com/apollographql/apollo-client/pull/12809) [`e2a0be8`](https://github.com/apollographql/apollo-client/commit/e2a0be8c3f8b242706f90e0dcc022628992a8ae8) Thanks [@jerelmiller](https://github.com/jerelmiller)! - The `ApolloLink.Request` (i.e. `GraphQLRequest`) passed to `ApolloLink.execute` no longer accepts `operationName` and `operationType` options. These properties are derived from the `query` and set on the returned `ApolloLink.Operation` type. - [#12712](https://github.com/apollographql/apollo-client/pull/12712) [`bbb2b61`](https://github.com/apollographql/apollo-client/commit/bbb2b61d259da54560a79813b130a977dae10523) Thanks [@jerelmiller](https://github.com/jerelmiller)! - An error is now thrown when trying to call `fetchMore` on a `cache-only` query. - [#12222](https://github.com/apollographql/apollo-client/pull/12222) [`d1a9054`](https://github.com/apollographql/apollo-client/commit/d1a905461d4378522c3257de00afba2ae8decd22) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Drop support for React 16. - [#12787](https://github.com/apollographql/apollo-client/pull/12787) [`8ce31fa`](https://github.com/apollographql/apollo-client/commit/8ce31fae54b1ae76c557f361cc946858cb2ff66b) Thanks [@phryneas](https://github.com/phryneas)! - Remove `DataProxy` namespace and interface. - [#12450](https://github.com/apollographql/apollo-client/pull/12450) [`876d070`](https://github.com/apollographql/apollo-client/commit/876d07042cf3348b3769b2bb415aa5f70ce9844c) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove `TSerialized` generic argument to `ApolloCache`. The `ApolloCache` base cache abstraction now returns `unknown` for `cache.extract` which can be overridden by a cache subclass. - [#12614](https://github.com/apollographql/apollo-client/pull/12614) [`d2851e2`](https://github.com/apollographql/apollo-client/commit/d2851e2c74541995760a86904b1e3ab4bd736e62) Thanks [@jerelmiller](https://github.com/jerelmiller)! - The `getCacheKey` function is no longer available from `operation.getContext()` in the link chain. Use `operation.client.cache.identify(obj)` in the link chain instead. - [#12376](https://github.com/apollographql/apollo-client/pull/12376) [`a0c996a`](https://github.com/apollographql/apollo-client/commit/a0c996a816fbb6a2323231c0422d1c8a3e20cbaf) Thanks [@jerelmiller](https://github.com/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. - [#12644](https://github.com/apollographql/apollo-client/pull/12644) [`fe2f005`](https://github.com/apollographql/apollo-client/commit/fe2f005c34913ae082b96a807dc240e2785d50bd) Thanks [@jerelmiller](https://github.com/jerelmiller)! - More strictly adhere to the [GraphQL over HTTP spec](https://graphql.github.io/graphql-over-http/draft/). This change adds support for the `application/graphql-response+json` media type and modifies the behavior of the `application/json` media type. - The client will parse the response as a well-formed GraphQL response when the server encodes `content-type` using `application/graphql-response+json` with a non-200 status code. - The client will now throw a `ServerError` when the server encodes `content-type` using `application/json` and returns a non-200 status code. - The client will now throw a `ServerError` when the server encodes using any other `content-type` and returns a non-200 status code. NOTE: If you use a testing utility to mock requests in your test, you may experience different behavior than production if your testing utility responds as `application/json` but your production server responds as `application/graphql-response+json`. If a `content-type` header is not set, the client interprets the response as `application/json`. - [#12600](https://github.com/apollographql/apollo-client/pull/12600) [`34ff6aa`](https://github.com/apollographql/apollo-client/commit/34ff6aa25b47c3e84d0b18e2c69bc995814bf2f2) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Move most of the utilities in `@apollo/client/utilities` to `@apollo/client/utilities/internal`. Many of the utilities exported from the `@apollo/client/utilities` endpoint were not considered stable. As a result of this change, utilities or types exported from `@apollo/client/utilities` are now documented and considered stable and will not undergo breaking changes. - [#12513](https://github.com/apollographql/apollo-client/pull/12513) [`9c3207c`](https://github.com/apollographql/apollo-client/commit/9c3207c44ddad1f8b845c09495d6c070ace8de7b) Thanks [@phryneas](https://github.com/phryneas)! - Removed the `@apollo/client/react/context` and `@apollo/client/react/hooks` entry points. Please use `@apollo/client/react` instead. - [#12384](https://github.com/apollographql/apollo-client/pull/12384) [`6aa6fd3`](https://github.com/apollographql/apollo-client/commit/6aa6fd316cfdb31ebbe3e3133cca2965604e7ca1) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Unusubscribing from `ObservableQuery` while a request is in flight will no longer terminate the request by unsubscribing from the link observable. - [#12463](https://github.com/apollographql/apollo-client/pull/12463) [`3868df8`](https://github.com/apollographql/apollo-client/commit/3868df81f973dc7b5a79fadf4dc1b0e291003b7f) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `ObservableQuery.setOptions` has been removed as it was an alias of `reobserve`. Prefer using `reobserve` directly instead. ```diff const observable = client.watchQuery(options); // Use reobserve to set new options and reevaluate the query - observable.setOptions(newOptions); + observable.reobserve(newOptions); ``` As a result of this change, `reobserve` has been marked for public use and is no longer considered an internal API. The `newNetworkStatus` argument has been removed to facilitate this change. - [#12478](https://github.com/apollographql/apollo-client/pull/12478) [`5ea6a45`](https://github.com/apollographql/apollo-client/commit/5ea6a45b3ec2f0d526abe78ae03c42bb519f87c7) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove `variables` from the result returned from `useSubscription`. - [#12735](https://github.com/apollographql/apollo-client/pull/12735) [`5159880`](https://github.com/apollographql/apollo-client/commit/51598808851e16af722baaefbd1f90534332e07a) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove deprecated `resultCacheMaxSize` option from `InMemoryCache` options. - [#12673](https://github.com/apollographql/apollo-client/pull/12673) [`cee90ab`](https://github.com/apollographql/apollo-client/commit/cee90abcd2a9c91c5fdf872cf2d1c12deaa6593e) Thanks [@phryneas](https://github.com/phryneas)! - The `ApolloClient` constructor options `name` and `version` that are used to configure the client awareness feature have moved onto a `clientAwareness` key. ```diff const client = new ApolloClient({ // .. - name: "my-app", - version: "1.0.0", + clientAwareness: { + name: "my-app", + version: "1.0.0", + }, }); ``` - [#12367](https://github.com/apollographql/apollo-client/pull/12367) [`e6af35e`](https://github.com/apollographql/apollo-client/commit/e6af35ed30c732ad834e6c524bc9ce5adbe5f706) Thanks [@jerelmiller](https://github.com/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. - [#12690](https://github.com/apollographql/apollo-client/pull/12690) [`5812759`](https://github.com/apollographql/apollo-client/commit/5812759b6659df49277635e89492c0d72c3b57d6) Thanks [@phryneas](https://github.com/phryneas)! - Aliasing any other field to `__typename` is now forbidden. - [#12556](https://github.com/apollographql/apollo-client/pull/12556) [`c3fceda`](https://github.com/apollographql/apollo-client/commit/c3fceda86c5e0f499d0b5fa54ea7dc4c4391ae2c) Thanks [@phryneas](https://github.com/phryneas)! - `ObservableQuery` will now keep previous `data` around when emitting a `loading` state, unless `query` or `variables` changed. Note that `@exports` variables are not taken into account for this, so `data` will stay around even if they change. - [#12776](https://github.com/apollographql/apollo-client/pull/12776) [`bce9b74`](https://github.com/apollographql/apollo-client/commit/bce9b7448a226b109cbe8f14911503fb09f37825) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Report masked fragments as complete even when a nested masked fragment contains partial data. - [#12788](https://github.com/apollographql/apollo-client/pull/12788) [`4179446`](https://github.com/apollographql/apollo-client/commit/417944677d2e79606b0f6cabd8d5d8b2063c876b) Thanks [@phryneas](https://github.com/phryneas)! - `TVariables` now always `extends OperationVariables` in all interfaces. - [#12224](https://github.com/apollographql/apollo-client/pull/12224) [`51e6c0f`](https://github.com/apollographql/apollo-client/commit/51e6c0f8657d20cedc570c6e9a244f877047dd61) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove deprecated `partialRefetch` option. - [#12407](https://github.com/apollographql/apollo-client/pull/12407) [`8b1390b`](https://github.com/apollographql/apollo-client/commit/8b1390bf0050c6bd4d5a32b67c3b96369d0552d4) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Calling `refetch` with new variables will now set the `networkStatus` to `refetch` instead of `setVariables`. - [#12476](https://github.com/apollographql/apollo-client/pull/12476) [`6afff60`](https://github.com/apollographql/apollo-client/commit/6afff60beece953406af2cbe07f7ccbf973cadaa) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Subscriptions now emit a `SubscribeResult` instead of a `FetchResult`. As a result, the `errors` field has been removed in favor of `error`. - [#12457](https://github.com/apollographql/apollo-client/pull/12457) [`32e85ea`](https://github.com/apollographql/apollo-client/commit/32e85ea9eb93c1ffb10d6f70e9e2775e1326e9aa) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Network errors triggered by queries now adhere to the `errorPolicy`. This means that GraphQL errors and network errors now behave the same way. Previously promise-based APIs, such as `client.query`, would reject the promise with the network error even if `errorPolicy` was set to `ignore`. The promise is now resolved with the `error` property set to the network error instead. - [#12840](https://github.com/apollographql/apollo-client/pull/12840) [`83e132a`](https://github.com/apollographql/apollo-client/commit/83e132ab1bacb3293da61dd4519379e36a1fb090) Thanks [@phryneas](https://github.com/phryneas)! - If you use an incremental delivery handler, you now have to explicitly opt into adding the chunk types to the `ApolloLink.Result` type. ```ts title="apollo-client.d.ts import { Defer20220824Handler } from "@apollo/client/incremental"; declare module "@apollo/client" { export interface TypeOverrides extends Defer20220824Handler.TypeOverrides {} } ``` - [#12712](https://github.com/apollographql/apollo-client/pull/12712) [`bbb2b61`](https://github.com/apollographql/apollo-client/commit/bbb2b61d259da54560a79813b130a977dae10523) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `cache-only` queries are no longer refetched when calling `client.reFetchObservableQueries` when `includeStandby` is `true`. - [#12808](https://github.com/apollographql/apollo-client/pull/12808) [`8e31a23`](https://github.com/apollographql/apollo-client/commit/8e31a2303b18f6fc4d8ec1cf4c01bf26b90f3f0b) Thanks [@phryneas](https://github.com/phryneas)! - HTTP Multipart handling will now throw an error if the connection closed before the final boundary has been received. Data after the final boundary will be ignored. - [#12384](https://github.com/apollographql/apollo-client/pull/12384) [`6aa6fd3`](https://github.com/apollographql/apollo-client/commit/6aa6fd316cfdb31ebbe3e3133cca2965604e7ca1) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the `iterateObserversSafely` utility function. - [#12825](https://github.com/apollographql/apollo-client/pull/12825) [`292b949`](https://github.com/apollographql/apollo-client/commit/292b949e9e1d10a715e0fd403737361f91432fbf) Thanks [@jerelmiller](https://github.com/jerelmiller)! - The `serializeFetchParameter` helper is no longer exported and `JSON.stringify` is used directly. As such, the `ClientParseError` type has also been removed in favor of throwing any JSON serialize errors directly. - [#12595](https://github.com/apollographql/apollo-client/pull/12595) [`60bb49c`](https://github.com/apollographql/apollo-client/commit/60bb49ccea9aecf3e6a212b5a1f71907e60af886) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the `@apollo/client/testing/experimental` test utilities. Use [GraphQL Testing Library](https://github.com/apollographql/graphql-testing-library) instead. - [#12718](https://github.com/apollographql/apollo-client/pull/12718) [`ecfc02a`](https://github.com/apollographql/apollo-client/commit/ecfc02a37908b58d1f799f0e817cdeab98482720) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Version bump only to release latest as `rc`. - [#12470](https://github.com/apollographql/apollo-client/pull/12470) [`d32902f`](https://github.com/apollographql/apollo-client/commit/d32902f26a4c5dea30421ee52aeea52df3e5334e) Thanks [@phryneas](https://github.com/phryneas)! - `ssrMode`, `ssrForceFetchDelay` and `disableNetworkFetches` have been reworked: Previously, a `ObservableQuery` created by `client.query` or `client.watchQuery` while one of those were active would permanently be changed from a `fetchPolicy` of `"network-only"` or `"cache-and-network"` to `"cache-first"`, and stay that way even long after `disableNetworkFetches` would have been deactivated. Now, the `ObservableQuery` will keep their original `fetchPolicy`, but queries made during `disableNetworkFetches` will just apply the `fetchPolicy` replacement at request time, just for that one request. `ApolloClient.disableNetworkFetches` has been renamed to `ApolloClient.prioritizeCacheValues` to better reflect this behaviour. - [#12559](https://github.com/apollographql/apollo-client/pull/12559) [`49ace0e`](https://github.com/apollographql/apollo-client/commit/49ace0e2119b7fd5997dcf051002ebd4ba2e0bc4) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `ObservableQuery.variables` can now be reset back to empty when calling `reobserve` with `variables: undefined`. Previously the `variables` key would be ignored so `variables` would remain unchanged. - [#12559](https://github.com/apollographql/apollo-client/pull/12559) [`49ace0e`](https://github.com/apollographql/apollo-client/commit/49ace0e2119b7fd5997dcf051002ebd4ba2e0bc4) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `never` is no longer supported as a valid `TVariables` generic argument for APIs that require `variables` as part of its type. Use `Record<string, never>` instead. - [#12735](https://github.com/apollographql/apollo-client/pull/12735) [`5159880`](https://github.com/apollographql/apollo-client/commit/51598808851e16af722baaefbd1f90534332e07a) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove deprecated `connectToDevtools` option from `ApolloClientOptions`. Use `devtools.enabled` instead. - [#12576](https://github.com/apollographql/apollo-client/pull/12576) [`a92ff78`](https://github.com/apollographql/apollo-client/commit/a92ff780abee60896bb9632867e90c82d0829255) Thanks [@jerelmiller](https://github.com/jerelmiller)! - The `cache` and `forceFetch` properties are no longer available on context when calling `operation.getContext()`. `cache` can be accessed through the `operation` with `operation.client.cache` instead. `forceFetch` has been replaced with `queryDeduplication` which specifies whether `queryDeduplication` was enabled for the request or not. - [#12533](https://github.com/apollographql/apollo-client/pull/12533) [`73221d8`](https://github.com/apollographql/apollo-client/commit/73221d87bd5640986f86fe3ee50c63ed49834cbb) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the `onError` and `setOnError` methods from `ApolloLink`. `onError` was only used by `MockLink` to rewrite errors if `setOnError` was used. - [#12485](https://github.com/apollographql/apollo-client/pull/12485) [`d338303`](https://github.com/apollographql/apollo-client/commit/d3383033d306b7d66e90f5f3170c24453cd76464) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Throw an error for queries and mutations if the link chain completes without emitting a value. - [#12556](https://github.com/apollographql/apollo-client/pull/12556) [`c3fceda`](https://github.com/apollographql/apollo-client/commit/c3fceda86c5e0f499d0b5fa54ea7dc4c4391ae2c) Thanks [@phryneas](https://github.com/phryneas)! - Removed `getLastResult`, `getLastError` and `resetLastResults` from `ObservableQuery` - [#12663](https://github.com/apollographql/apollo-client/pull/12663) [`01512f2`](https://github.com/apollographql/apollo-client/commit/01512f2429dd394fb72b8ba9284047a09ade666f) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Unsubscribing from an `ObservableQuery` before a value has been emitted will remove the query from the tracked list of queries and will no longer be eligible for query deduplication. - [#12809](https://github.com/apollographql/apollo-client/pull/12809) [`e2a0be8`](https://github.com/apollographql/apollo-client/commit/e2a0be8c3f8b242706f90e0dcc022628992a8ae8) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `operation.operationType` is now a non-null `OperationTypeNode`. It is now safe to compare this value without having to check for `undefined`. - [#12398](https://github.com/apollographql/apollo-client/pull/12398) [`8cf5077`](https://github.com/apollographql/apollo-client/commit/8cf5077bed1ab46fdd32c5e253071506c0076064) Thanks [@jerelmiller](https://github.com/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. ## Migration guide `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 server - `networkError` - Any non-GraphQL error that caused the query to fail - `protocolErrors` - Transport-level errors that occur during [multipart HTTP subscriptions](https://www.apollographql.com/docs/graphos/routing/operations/subscriptions/multipart-protocol) - `clientErrors` - 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`. ### `graphqlErrors` GraphQL errors are now encapsulated in a `CombinedGraphQLErrors` instance. You can access the raw GraphQL errors via the `errors` property. ```js import { CombinedGraphQLErrors } from "@apollo/client"; // ... const { error } = useQuery(query); if (error && error instanceof CombinedGraphQLErrors) { console.log(error.errors); } ``` ### `networkError` Network errors are no longer wrapped and are instead passed through directly. ```js 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')`; ``` ### `protocolErrors` Protocol errors are now encapsulated in a `CombinedProtocolErrors` instance. You can access the raw protocol errors via the `errors` property. ```js import { CombinedProtocolErrors } from "@apollo/client"; // ... const { error } = useSubscription(subscription); if (error && error instanceof CombinedProtocolErrors) { console.log(error.errors); } ``` ### `clientErrors` These were unused by the client and have no replacement. Any non-GraphQL or non-protocol errors are now passed through unwrapped. ### Strings as errors 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`. ```js 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')`; ``` ### Non-error types If the link chain sends any other object type as an error, Apollo Client will wrap this in an `UnknownError` instance with the [`cause`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error/cause) set to the original object. This ensures `error` properties are guaranteed to be of type `Error`. ```js 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. ``` - [#12809](https://github.com/apollographql/apollo-client/pull/12809) [`e2a0be8`](https://github.com/apollographql/apollo-client/commit/e2a0be8c3f8b242706f90e0dcc022628992a8ae8) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `operation.operationName` is now set as `string | undefined` where `undefined` represents an anonymous query. Previously `operationName` would return an empty string as the `operationName` for anonymous queries. - [#12450](https://github.com/apollographql/apollo-client/pull/12450) [`876d070`](https://github.com/apollographql/apollo-client/commit/876d07042cf3348b3769b2bb415aa5f70ce9844c) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the `TCacheShape` generic argument to `ApolloClient`. `client.extract()` now returns `unknown` by default. You will either need to type-cast this to the expected serialized shape, or use the `cache.extract()` directly from the subclass to get more specific types. - [#12774](https://github.com/apollographql/apollo-client/pull/12774) [`511b4f3`](https://github.com/apollographql/apollo-client/commit/511b4f3e792a75aa5aa27b335e8119dbc2a9c254) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Apply document transforms before reading data from the cache for `client.readQuery`, `client.readFragment`, `client.watchFragment`, `useFragment`, and `useSuspenseFragment`. NOTE: This change does not affect the equivalent `cache.*` APIs. To read data from the cache without first running document transforms, run `cache.readQuery`, `cache.readFragment`, etc. - [#12705](https://github.com/apollographql/apollo-client/pull/12705) [`a60f411`](https://github.com/apollographql/apollo-client/commit/a60f411e58cc67730d0dc4513e4045f004027ded) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `cache-only` queries will now initialize with `loading: false` and `networkStatus: NetworkStatus.ready` when there is no data in the cache. This means `useQuery` will no longer render a short initial loading state before rendering `loading: false` and `ObservableQuery.getCurrentResult()` will now return `loading: false` immediately. - [#12475](https://github.com/apollographql/apollo-client/pull/12475) [`3de63eb`](https://github.com/apollographql/apollo-client/commit/3de63ebcdf95a87adc31e6b4a39cae5391ed945a) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Unify error behavior on mutations for GraphQL errors and network errors by ensuring network errors are subject to the `errorPolicy`. Network errors created when using an `errorPolicy` of `all` will now resolve the promise and be returned on the `error` property of the result, or stripped away when the `errorPolicy` is `none`. - [#12384](https://github.com/apollographql/apollo-client/pull/12384) [`6aa6fd3`](https://github.com/apollographql/apollo-client/commit/6aa6fd316cfdb31ebbe3e3133cca2965604e7ca1) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove `fromError` utility function. Use [`throwError`](https://rxjs.dev/api/index/function/throwError) instead. - [#12649](https://github.com/apollographql/apollo-client/pull/12649) [`0be92ad`](https://github.com/apollographql/apollo-client/commit/0be92ad51cf8de444fa1cc507bab2c21d230a44e) Thanks [@jerelmiller](https://github.com/jerelmiller)! - The `TData` generic provided to types that return a `dataState` property is now modified by the given `DataState` generic instead of passing a modified `TData` type. For example, a `QueryRef` that could return partial data was defined as `QueryRef<DeepPartial<TData>, TVariables>`. Now `TData` should be provided unmodified and a set of allowed states should be given instead: `QueryRef<TData, TVariables, 'complete' | 'streaming' | 'partial'>`. To migrate, use the following guide to replace your type with the right set of states (all types listed below are changed the same way): ```diff - QueryRef<TData, TVariables> // `QueryRef`'s default is 'complete' | 'streaming' so this can also be left alone if you prefer // All other types affected by this change default to all states + QueryRef<TData, TVariables> + QueryRef<TData, TVariables, 'complete' | 'streaming'> - QueryRef<TData | undefined, TVariables> + QueryRef<TData, TVariables, 'complete' | 'streaming' | 'empty'> - QueryRef<DeepPartial<TData>, TVariables> + QueryRef<TData, TVariables, 'complete' | 'streaming' | 'partial'> - QueryRef<DeepPartial<TData> | undefined, TVariables> + QueryRef<TData, TVariables, 'complete' | 'streaming' | 'partial' | 'empty'> ``` The following types are affected. Provide the allowed `dataState` values to the `TDataState` generic: - `ApolloQueryResult` - `QueryRef` - `PreloadedQueryRef` - `useLazyQuery.Result` - `useQuery.Result` - `useReadQuery.Result` - `useSuspenseQuery.Result` All `*QueryRef` types default to `complete | streaming` states while the rest of the types default to `'complete' | 'streaming' | 'partial' | 'empty'` states. You shouldn't need to provide the states unless you need to either allow for partial data/empty values (`*QueryRef`) or a restricted set of states. - [#12850](https://github.com/apollographql/apollo-client/pull/12850) [`268cd80`](https://github.com/apollographql/apollo-client/commit/268cd800a2d73305c0df8dd38b6bd1cee98f0fec) Thanks [@phryneas](https://github.com/phryneas)! - Introduce a versioning policy. - [#12809](https://github.com/apollographql/apollo-client/pull/12809) [`e2a0be8`](https://github.com/apollographql/apollo-client/commit/e2a0be8c3f8b242706f90e0dcc022628992a8ae8) Thanks [@jerelmiller](https://github.com/jerelmiller)! - The `concat`, `from`, and `split` functions on `ApollLink` no longer support a plain request handler function. Please wrap the request handler with `new ApolloLink`. ```diff const link = new ApolloLink(/* ... */); link.concat( - (operation, forward) => forward(operation), + new ApolloLink((operation, forward) => forward(operation)), ); ``` - [#12802](https://github.com/apollographql/apollo-client/pull/12802) [`e2b51b3`](https://github.com/apollographql/apollo-client/commit/e2b51b30acbd360253100f9d2a91fe7e0c57be4c) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Disallow the `mutation` option for the `mutate` function returned from `useMutation`. - [#12211](https://github.com/apollographql/apollo-client/pull/12211) [`c2736db`](https://github.com/apollographql/apollo-client/commit/c2736db3ad6f8b6e56f065682d5b76614f41bfd4) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove the deprecated `graphql`, `withQuery`, `withMutation`, `withSubscription`, and `withApollo` hoc components. Use the provided React hooks instead. - [#12690](https://github.com/apollographql/apollo-client/pull/12690) [`5812759`](https://github.com/apollographql/apollo-client/commit/5812759b6659df49277635e89492c0d72c3b57d6) Thanks [@phryneas](https://github.com/phryneas)! - Aliasing a field to an alias beginning with `__ac_` is now forbidden - this namespace is now reserved for internal use. - [#12559](https://github.com/apollographql/apollo-client/pull/12559) [`49ace0e`](https://github.com/apollographql/apollo-client/commit/49ace0e2119b7fd5997dcf051002ebd4ba2e0bc4) Thanks [@jerelmiller](https://github.com/jerelmiller)! - When passing a `variables` key with the value `undefined`, the value will be replaced by the default value in the query, if it is provided, rather than leave it as `undefined`. ```ts // given this query const query = gql` query PaginatedQuery($limit: Int! = 10, $offset: Int) { list(limit: $limit, offset: $offset) { id } } `; const observable = client.query({ query, variables: { limit: 5, offset: 0 }, }); console.log(observable.variables); // => { limit: 5, offset: 0 } observable.reobserve({ variables: { limit: undefined, offset: 10 } }); // limit is now `10`. This would previously be `undefined` console.log(observable.variables); // => { limit: 10, offset: 10 } ``` - [#12262](https://github.com/apollographql/apollo-client/pull/12262) [`10ef733`](https://github.com/apollographql/apollo-client/commit/10ef7338cdcbbaf75d806f426e9708c9e095c2da) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Remove `itAsync` test utility. - [#12673](https://github.com/apollographql/apollo-client/pull/12673) [`cee90ab`](https://github.com/apollographql/apollo-client/commit/cee90abcd2a9c91c5fdf872cf2d1c12deaa6593e) Thanks [@phryneas](https://github.com/phryneas)! - Adds enhanced client awareness to the client. `HttpLink` and `BatchHttpLink` will now per default send information about the client library you are using in `extensions`. This could look like this: ```json { "query": "query GetUser($id: ID!) { user(id: $id) { __typename id name } }", "variables": { "id": 5 }, "extensions": { "clientLibrary": { "name": "@apollo/client", "version": "4.0.0" } } } ``` This feature can be disabled by passing `enhancedClientAwareness: { transport: false }` to your `ApolloClient`, `HttpLink` or `BatchHttpLink` constructor options. - [#12742](https://github.com/apollographql/apollo-client/pull/12742) [`575bf3e`](https://github.com/apollographql/apollo-client/commit/575bf3ed5885efb09c1eec497af4d2690c6b87d4) Thanks [@jerelmiller](https://github.com/jerelmiller)! - The new `SetContextLink` flips the `prevContext` and `operation` arguments in the callback. The `setContext` function has remained unchanged. ```diff - new SetContextLink((operation, prevContext) => { + new SetContextLink((prevContext, operation) => { // ... }) ``` - [#12536](https://github.com/apollographql/apollo-client/pull/12536) [`e14205a`](https://github.com/apollographql/apollo-client/commit/e14205ad5909f95aa04684acd0ca2f25956ee50c) Thanks [@jerelmiller](https://github.com/jerelmiller)! - An initial loading state is now emitted from `ObservableQuery` when subscribing if `notifyOnNetworkStatusChange` is set to `true`. - [#12465](https://github.com/apollographql/apollo-client/pull/12465) [`a132163`](https://github.com/apollographql/apollo-client/commit/a1321637cafb4023d6df416e9467294114d8346b) Thanks [@jerelmiller](https://github.com/jerelmiller)! - Flatten out React hook types. As a result, the base types have been removed. Prefer using the hook types instead. Removed types include: - `BaseMutationOptions` - `BaseQueryOptions` - `BaseSubscriptionOptions` - `ObservableQueryFields` - `MutationSharedOptions` - `QueryFunctionOptions` - [#12675](https://github.com/apollographql/apollo-client/pull/12675) [`8f1d974`](https://github.com/apollographql/apollo-client/commit/8f1d974881ff54339b6b6593a219ba6d5fd013c0) Thanks [@phryneas](https://github.com/phryneas)! - `ObservableQuery` no longer has a `queryId` property. `ApolloClient.getObservableQueries` no longer returns a `Map<string, ObservableQuery>`, but a `Set<ObservableQuery>`. - [#12398](https://github.com/apollographql/apollo-client/pull/12398) [`8cf5077`](https://github.com/apollographql/apollo-client/commit/8cf5077bed1ab46fdd32c5e253071506c0076064) Thanks [@jerelmiller](https://github.com/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. ```js import { ServerError, ServerParseError } from "@apollo/client"; if (error instanceof ServerError) { // ... } if (error instanceof ServerParseError) { // ... } ``` - [#12712](https://github.com/apollographql/apollo-client/pull/12712) [`bbb2b61`](https://github.com/apollographql/apollo-client/commit/bbb2b61d259da54560a79813b130a977dae10523) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `cache-only` queries are now excluded from `client.refetchQueries` in all situations. `cache-only` queries affected by `updateCache` are also excluded from `refetchQueries` when `onQueryUpdated` is not provided. - [#12463](https://github.com/apollographql/apollo-client/pull/12463) [`3868df8`](https://github.com/apollographql/apollo-client/commit/3868df81f973dc7b5a79fadf4dc1b0e291003b7f) Thanks [@jerelmiller](https://github.com/jerelmiller)! - `useQuery` no longer returns `reobserve` as part of its result. It was possible to use `reobserve` to set new options on the underlying `ObservableQuery` instance which differed from the options passed to the hook. This could result in unexpe