@apollo/client
Version:
A fully-featured caching GraphQL client.
785 lines (532 loc) • 683 kB
Markdown
# @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