PackageTrack

npm · #4032

@apollo/client

4.2.12apollographql/apollo-client

A fully-featured caching GraphQL client.

Release timeline

723 releases since 2019
2020202120222023202420252026

Releases

  1. 3.9.47 Feb 2024
    Release notes3 sources agree

    Patch Changes

    • #11403 b0c4f3a Thanks @jerelmiller! - Fix issue in useLazyQuery that results in a double network call when calling the execute function with no arguments after having called it previously with another set of arguments.

    • #11576 e855d00 Thanks @alessbell! - Revert PR #11202 to fix caching bug reported in #11560

    Open source →
  2. 3.9.36 Feb 2024
    Release notes3 sources agree

    Patch Changes

    Open source →
  3. 3.9.21 Feb 2024
    Release notes3 sources agree

    Patch Changes

    Open source →
  4. 3.9.131 Jan 2024
    Release notes3 sources agree

    Patch Changes

    • #11516 8390fea Thanks @phryneas! - Fix an incorrect string substitution in a warning message.

    • #11515 c9bf93b Thanks @vladar! - Avoid redundant refetchQueries call for mutation with no-cache policy (fixes #10238)

    • #11545 84a6bea Thanks @alessbell! - Remove error thrown by inFlightLinkObservables intended to be removed before 3.9 release.

    Open source →
  5. 3.9.030 Jan 2024
    Release notes

    Minor Changes

    Memory optimizations

    • #11424 62f3b6d Thanks @phryneas! - Simplify RetryLink, fix potential memory leak

      Historically, RetryLink would keep a values array of all previous values, in case the operation would get an additional subscriber at a later point in time.

      In practice, this could lead to a memory leak (#11393) and did not serve any further purpose, as the resulting observable would only be subscribed to by Apollo Client itself, and only once - it would be wrapped in a Concast before being exposed to the user, and that Concast would handle subscribers on its own.

    • #11435 5cce53e Thanks @phryneas! - Deprecates canonizeResults.

      Using canonizeResults can result in memory leaks so we generally do not recommend using this option anymore. A future version of Apollo Client will contain a similar feature without the risk of memory leaks.

    • #11254 d08970d Thanks @benjamn! - Decouple canonicalStringify from ObjectCanon for better time and memory performance.

    • #11356 cc4ac7e Thanks @phryneas! - Fix a potential memory leak in FragmentRegistry.transform and FragmentRegistry.findFragmentSpreads that would hold on to passed-in DocumentNodes for too long.

    • #11370 25e2cb4 Thanks @phryneas! - parse function: improve memory management

      • use LRU WeakCache instead of Map to keep a limited number of parsed results
      • cache is initiated lazily, only when needed
      • expose parse.resetCache() method
    • #11389 139acd1 Thanks @phryneas! - documentTransform: use optimism and WeakCache instead of directly storing data on the Trie

    • #11358 7d939f8 Thanks @phryneas! - Fixes a potential memory leak in Concast that might have been triggered when Concast was used outside of Apollo Client.

    • #11344 bd26676 Thanks @phryneas! - Add a resetCache method to DocumentTransform and hook InMemoryCache.addTypenameTransform up to InMemoryCache.gc

    • #11367 30d17bf Thanks @phryneas! - print: use WeakCache instead of WeakMap

    • #11387 4dce867 Thanks @phryneas! - QueryManager.transformCache: use WeakCache instead of WeakMap

    • #11369 2a47164 Thanks @phryneas! - Persisted Query Link: improve memory management

      • use LRU WeakCache instead of WeakMap to keep a limited number of hash results
      • hash cache is initiated lazily, only when needed
      • expose persistedLink.resetHashCache() method
      • reset hash cache if the upstream server reports it doesn't accept persisted queries
    • #10804 221dd99 Thanks @phryneas! - use WeakMap in React Native with Hermes

    • #11355 7d8e184 Thanks @phryneas! - InMemoryCache.gc now also triggers FragmentRegistry.resetCaches (if there is a FragmentRegistry)

    • #11409 2e7203b Thanks @phryneas! - Adds an experimental ApolloClient.getMemoryInternals helper

    • #11343 776631d Thanks @phryneas! - Add reset method to print, hook up to InMemoryCache.gc

    Suspense-enabled data fetching on user interaction with useLoadableQuery

    • #11300 a815873 Thanks @jerelmiller! - Introduces a new useLoadableQuery hook. This hook works similarly to useBackgroundQuery in that it returns a queryRef that can be used to suspend a component via the useReadQuery hook. It provides a more ergonomic way to load the query during a user interaction (for example when wanting to preload some data) that would otherwise be clunky with useBackgroundQuery.

      function App() {
        const [loadQuery, queryRef, { refetch, fetchMore, reset }] =
          useLoadableQuery(query, options);
      
        return (
          <>
            <button onClick={() => loadQuery(variables)}>Load query</button>
            <Suspense fallback={<SuspenseFallback />}>
              {queryRef && <Child queryRef={queryRef} />}
            </Suspense>
          </>
        );
      }
      
      function Child({ queryRef }) {
        const { data } = useReadQuery(queryRef);
      
        // ...
      }
      

    Begin preloading outside of React with createQueryPreloader

    • #11412 58db5c3 Thanks @jerelmiller! - Add the ability to start preloading a query outside React to begin fetching as early as possible. Call createQueryPreloader to create a preloadQuery function which can be called to start fetching a query. This returns a queryRef which is passed to useReadQuery and suspended until the query is done fetching.

    Testing utility improvements

    • #11178 4d64a6f Thanks @sebakerckhof! - Support re-using of mocks in the MockedProvider

    • #6701 8d2b4e1 Thanks @prowe! - Ability to dynamically match mocks

      Adds support for a new property MockedResponse.variableMatcher: a predicate function that accepts a variables param. If true, the variables will be passed into the ResultFunction to help dynamically build a response.

    New useQueryRefHandlers hook

    • #11412 58db5c3 Thanks @jerelmiller! - Create a new useQueryRefHandlers hook that returns refetch and fetchMore functions for a given queryRef. This is useful to get access to handlers for a queryRef that was created by createQueryPreloader or when the handlers for a queryRef produced by a different component are inaccessible.

      const MyComponent({ queryRef }) {
        const { refetch, fetchMore } = useQueryRefHandlers(queryRef);
      
        // ...
      }
      

    Bail out of optimisticResponse updates with the IGNORE sentinel object

    • #11410 07fcf6a Thanks @sf-twingate! - Allow returning IGNORE sentinel object from optimisticResponse functions to bail-out from the optimistic update.

      Consider this example:

      const UPDATE_COMMENT = gql`
        mutation UpdateComment($commentId: ID!, $commentContent: String!) {
          updateComment(commentId: $commentId, content: $commentContent) {
            id
            __typename
            content
          }
        }
      `;
      
      function CommentPageWithData() {
        const [mutate] = useMutation(UPDATE_COMMENT);
        return (
          <Comment
            updateComment={({ commentId, commentContent }) =>
              mutate({
                variables: { commentId, commentContent },
                optimisticResponse: (vars, { IGNORE }) => {
                  if (commentContent === "foo") {
                    // conditionally bail out of optimistic updates
                    return IGNORE;
                  }
                  return {
                    updateComment: {
                      id: commentId,
                      __typename: "Comment",
                      content: commentContent,
                    },
                  };
                },
              })
            }
          />
        );
      }
      

      The IGNORE sentinel can be destructured from the second parameter in the callback function signature passed to optimisticResponse.

      const preloadQuery = createQueryPreloader(client);
      const queryRef = preloadQuery(QUERY, { variables, ...otherOptions });
      
      function App() {
        return {
          <Suspense fallback={<div>Loading</div>}>
            <MyQuery />
          </Suspense>
        }
      }
      
      function MyQuery() {
        const { data } = useReadQuery(queryRef);
      
        // do something with data
      }
      

    Network adapters for multipart subscriptions usage with Relay and urql

    • #11301 46ab032 Thanks @alessbell! - Add multipart subscription network adapters for Relay and urql

      Relay
      import { createFetchMultipartSubscription } from "@apollo/client/utilities/subscriptions/relay";
      import { Environment, Network, RecordSource, Store } from "relay-runtime";
      
      const fetchMultipartSubs = createFetchMultipartSubscription(
        "http://localhost:4000",
      );
      
      const network = Network.create(fetchQuery, fetchMultipartSubs);
      
      export const RelayEnvironment = new Environment({
        network,
        store: new Store(new RecordSource()),
      });
      
      Urql
      import { createFetchMultipartSubscription } from "@apollo/client/utilities/subscriptions/urql";
      import { Client, fetchExchange, subscriptionExchange } from "@urql/core";
      
      const url = "http://localhost:4000";
      
      const multipartSubscriptionForwarder = createFetchMultipartSubscription(url);
      
      const client = new Client({
        url,
        exchanges: [
          fetchExchange,
          subscriptionExchange({
            forwardSubscription: multipartSubscriptionForwarder,
          }),
        ],
      });
      

    skipPollAttempt callback function

    • #11397 3f7eecb Thanks @aditya-kumawat! - Adds a new skipPollAttempt callback function that's called whenever a refetch attempt occurs while polling. If the function returns true, the refetch is skipped and not reattempted until the next poll interval. This will solve the frequent use-case of disabling polling when the window is inactive.

      useQuery(QUERY, {
        pollInterval: 1000,
        skipPollAttempt: () => document.hidden, // or !document.hasFocus()
      });
      // or define it globally
      new ApolloClient({
        defaultOptions: {
          watchQuery: {
            skipPollAttempt: () => document.hidden, // or !document.hasFocus()
          },
        },
      });
      

    QueryManager.inFlightLinkObservables now uses a strong Trie as an internal data structure

    • #11345 1759066 Thanks @phryneas!

      Warning: requires @apollo/experimental-nextjs-app-support update

      If you are using @apollo/experimental-nextjs-app-support, you will need to update that to at least 0.5.2, as it accesses this internal data structure.

    <details open> <summary><h4>More Minor Changes</h4></summary>

    • #11202 7c2bc08 Thanks @benjamn! - Prevent QueryInfo#markResult mutation of result.data and return cache data consistently whether complete or incomplete.

    • #11442 4b6f2bc Thanks @jerelmiller! - Remove the need to call retain from useLoadableQuery since useReadQuery will now retain the query. This means that a queryRef that is not consumed by useReadQuery within the given autoDisposeTimeoutMs will now be auto diposed for you.

      Thanks to #11412, disposed query refs will be automatically resubscribed to the query when consumed by useReadQuery after it has been disposed.

    • #11438 6d46ab9 Thanks @jerelmiller! - Remove the need to call retain from useBackgroundQuery since useReadQuery will now retain the query. This means that a queryRef that is not consumed by useReadQuery within the given autoDisposeTimeoutMs will now be auto diposed for you.

      Thanks to #11412, disposed query refs will be automatically resubscribed to the query when consumed by useReadQuery after it has been disposed.

    • #11175 d6d1491 Thanks @phryneas! - To work around issues in React Server Components, especially with bundling for the Next.js "edge" runtime we now use an external package to wrap react imports instead of importing React directly.

    • #11495 1190aa5 Thanks @jerelmiller! - Increase the default memory limits for executeSelectionSet and executeSelectionSetArray.

    </details>

    <details open> <summary><h3>Patch Changes</h3></summary>

    • #11275 3862f9b Thanks @phryneas! - Add a defaultContext option and property on ApolloClient, e.g. for keeping track of changing auth tokens or dependency injection.

      This can be used e.g. in authentication scenarios, where a new token might be generated outside of the link chain and should passed into the link chain.

      import { ApolloClient, createHttpLink, InMemoryCache } from "@apollo/client";
      import { setContext } from "@apollo/client/link/context";
      
      const httpLink = createHttpLink({
        uri: "/graphql",
      });
      
      const authLink = setContext((_, { headers, token }) => {
        return {
          headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : "",
          },
        };
      });
      
      const client = new ApolloClient({
        link: authLink.concat(httpLink),
        cache: new InMemoryCache(),
      });
      
      // somewhere else in your application
      function onNewToken(newToken) {
        // token can now be changed for future requests without need for a global
        // variable, scoped ref or recreating the client
        client.defaultContext.token = newToken;
      }
      
    • #11443 ff5a332 Thanks @phryneas! - Adds a deprecation warning to the HOC and render prop APIs.

      The HOC and render prop APIs have already been deprecated since 2020, but we previously didn't have a @deprecated tag in the DocBlocks.

    • #11385 d9ca4f0 Thanks @phryneas! - ensure defaultContext is also used for mutations and subscriptions

    • #11503 67f62e3 Thanks @jerelmiller! - Release changes from v3.8.10

    • #11078 14edebe Thanks @phryneas! - ObservableQuery: prevent reporting results of previous queries if the variables changed since

    • #11439 33454f0 Thanks @jerelmiller! - Address bundling issue introduced in #11412 where the react/cache internals ended up duplicated in the bundle. This was due to the fact that we had a react/hooks entrypoint that imported these files along with the newly introduced createQueryPreloader function, which lived outside of the react/hooks folder.

    • #11371 ebd8fe2 Thanks @phryneas! - Clarify types of EntityStore.makeCacheKey.

    </details>

    Open source →
    Additional notes2 sources agree

    Minor Changes

    Memory optimizations

    • #11424 62f3b6d Thanks @phryneas! - Simplify RetryLink, fix potential memory leak

      Historically, RetryLink would keep a values array of all previous values, in case the operation would get an additional subscriber at a later point in time.

      In practice, this could lead to a memory leak (#11393) and did not serve any further purpose, as the resulting observable would only be subscribed to by Apollo Client itself, and only once - it would be wrapped in a Concast before being exposed to the user, and that Concast would handle subscribers on its own.

    • #11435 5cce53e Thanks @phryneas! - Deprecates canonizeResults.

      Using canonizeResults can result in memory leaks so we generally do not recommend using this option anymore. A future version of Apollo Client will contain a similar feature without the risk of memory leaks.

    • #11254 d08970d Thanks @benjamn! - Decouple canonicalStringify from ObjectCanon for better time and memory performance.

    • #11356 cc4ac7e Thanks @phryneas! - Fix a potential memory leak in FragmentRegistry.transform and FragmentRegistry.findFragmentSpreads that would hold on to passed-in DocumentNodes for too long.

    • #11370 25e2cb4 Thanks @phryneas! - parse function: improve memory management

      • use LRU WeakCache instead of Map to keep a limited number of parsed results
      • cache is initiated lazily, only when needed
      • expose parse.resetCache() method
    • #11389 139acd1 Thanks @phryneas! - documentTransform: use optimism and WeakCache instead of directly storing data on the Trie

    • #11358 7d939f8 Thanks @phryneas! - Fixes a potential memory leak in Concast that might have been triggered when Concast was used outside of Apollo Client.

    • #11344 bd26676 Thanks @phryneas! - Add a resetCache method to DocumentTransform and hook InMemoryCache.addTypenameTransform up to InMemoryCache.gc

    • #11367 30d17bf Thanks @phryneas! - print: use WeakCache instead of WeakMap

    • #11387 4dce867 Thanks @phryneas! - QueryManager.transformCache: use WeakCache instead of WeakMap

    • #11369 2a47164 Thanks @phryneas! - Persisted Query Link: improve memory management

      • use LRU WeakCache instead of WeakMap to keep a limited number of hash results
      • hash cache is initiated lazily, only when needed
      • expose persistedLink.resetHashCache() method
      • reset hash cache if the upstream server reports it doesn't accept persisted queries
    • #10804 221dd99 Thanks @phryneas! - use WeakMap in React Native with Hermes

    • #11355 7d8e184 Thanks @phryneas! - InMemoryCache.gc now also triggers FragmentRegistry.resetCaches (if there is a FragmentRegistry)

    • #11409 2e7203b Thanks @phryneas! - Adds an experimental ApolloClient.getMemoryInternals helper

    • #11343 776631d Thanks @phryneas! - Add reset method to print, hook up to InMemoryCache.gc

    Suspense-enabled data fetching on user interaction with useLoadableQuery

    • #11300 a815873 Thanks @jerelmiller! - Introduces a new useLoadableQuery hook. This hook works similarly to useBackgroundQuery in that it returns a queryRef that can be used to suspend a component via the useReadQuery hook. It provides a more ergonomic way to load the query during a user interaction (for example when wanting to preload some data) that would otherwise be clunky with useBackgroundQuery.

      function App() {
        const [loadQuery, queryRef, { refetch, fetchMore, reset }] =
          useLoadableQuery(query, options);
      
        return (
          <>
            <button onClick={() => loadQuery(variables)}>Load query</button>
            <Suspense fallback={<SuspenseFallback />}>
              {queryRef && <Child queryRef={queryRef} />}
            </Suspense>
          </>
        );
      }
      
      function Child({ queryRef }) {
        const { data } = useReadQuery(queryRef);
      
        // ...
      }
      

    Begin preloading outside of React with createQueryPreloader

    • #11412 58db5c3 Thanks @jerelmiller! - Add the ability to start preloading a query outside React to begin fetching as early as possible. Call createQueryPreloader to create a preloadQuery function which can be called to start fetching a query. This returns a queryRef which is passed to useReadQuery and suspended until the query is done fetching.

      const preloadQuery = createQueryPreloader(client);
      const queryRef = preloadQuery(QUERY, { variables, ...otherOptions });
      
      function App() {
        return {
          <Suspense fallback={<div>Loading</div>}>
            <MyQuery />
          </Suspense>
        }
      }
      
      function MyQuery() {
        const { data } = useReadQuery(queryRef);
      
        // do something with data
      }
      

    Testing utility improvements

    • #11178 4d64a6f Thanks @sebakerckhof! - Support re-using of mocks in the MockedProvider

    • #6701 8d2b4e1 Thanks @prowe! - Ability to dynamically match mocks

      Adds support for a new property MockedResponse.variableMatcher: a predicate function that accepts a variables param. If true, the variables will be passed into the ResultFunction to help dynamically build a response.

    New useQueryRefHandlers hook

    • #11412 58db5c3 Thanks @jerelmiller! - Create a new useQueryRefHandlers hook that returns refetch and fetchMore functions for a given queryRef. This is useful to get access to handlers for a queryRef that was created by createQueryPreloader or when the handlers for a queryRef produced by a different component are inaccessible.

      const MyComponent({ queryRef }) {
        const { refetch, fetchMore } = useQueryRefHandlers(queryRef);
      
        // ...
      }
      

    Bail out of optimisticResponse updates with the IGNORE sentinel object

    • #11410 07fcf6a Thanks @sf-twingate! - Allow returning IGNORE sentinel object from optimisticResponse functions to bail-out from the optimistic update.

      Consider this example:

      const UPDATE_COMMENT = gql`
        mutation UpdateComment($commentId: ID!, $commentContent: String!) {
          updateComment(commentId: $commentId, content: $commentContent) {
            id
            __typename
            content
          }
        }
      `;
      
      function CommentPageWithData() {
        const [mutate] = useMutation(UPDATE_COMMENT);
        return (
          <Comment
            updateComment={({ commentId, commentContent }) =>
              mutate({
                variables: { commentId, commentContent },
                optimisticResponse: (vars, { IGNORE }) => {
                  if (commentContent === "foo") {
                    // conditionally bail out of optimistic updates
                    return IGNORE;
                  }
                  return {
                    updateComment: {
                      id: commentId,
                      __typename: "Comment",
                      content: commentContent,
                    },
                  };
                },
              })
            }
          />
        );
      }
      

      The IGNORE sentinel can be destructured from the second parameter in the callback function signature passed to optimisticResponse.

    Network adapters for multipart subscriptions usage with Relay and urql

    • #11301 46ab032 Thanks @alessbell! - Add multipart subscription network adapters for Relay and urql

      Relay
      import { createFetchMultipartSubscription } from "@apollo/client/utilities/subscriptions/relay";
      import { Environment, Network, RecordSource, Store } from "relay-runtime";
      
      const fetchMultipartSubs = createFetchMultipartSubscription(
        "http://localhost:4000"
      );
      
      const network = Network.create(fetchQuery, fetchMultipartSubs);
      
      export const RelayEnvironment = new Environment({
        network,
        store: new Store(new RecordSource()),
      });
      
      Urql
      import { createFetchMultipartSubscription } from "@apollo/client/utilities/subscriptions/urql";
      import { Client, fetchExchange, subscriptionExchange } from "@urql/core";
      
      const url = "http://localhost:4000";
      
      const multipartSubscriptionForwarder = createFetchMultipartSubscription(url);
      
      const client = new Client({
        url,
        exchanges: [
          fetchExchange,
          subscriptionExchange({
            forwardSubscription: multipartSubscriptionForwarder,
          }),
        ],
      });
      

    skipPollAttempt callback function

    • #11397 3f7eecb Thanks @aditya-kumawat! - Adds a new skipPollAttempt callback function that's called whenever a refetch attempt occurs while polling. If the function returns true, the refetch is skipped and not reattempted until the next poll interval. This will solve the frequent use-case of disabling polling when the window is inactive.

      useQuery(QUERY, {
        pollInterval: 1000,
        skipPollAttempt: () => document.hidden, // or !document.hasFocus()
      });
      // or define it globally
      new ApolloClient({
        defaultOptions: {
          watchQuery: {
            skipPollAttempt: () => document.hidden, // or !document.hasFocus()
          },
        },
      });
      

    QueryManager.inFlightLinkObservables now uses a strong Trie as an internal data structure

    • #11345 1759066 Thanks @phryneas!

      Warning: requires @apollo/experimental-nextjs-app-support update

      If you are using @apollo/experimental-nextjs-app-support, you will need to update that to at least 0.5.2, as it accesses this internal data structure.

    <details open> <summary><h4>More Minor Changes</h4></summary>

    • #11202 7c2bc08 Thanks @benjamn! - Prevent QueryInfo#markResult mutation of result.data and return cache data consistently whether complete or incomplete.

    • #11442 4b6f2bc Thanks @jerelmiller! - Remove the need to call retain from useLoadableQuery since useReadQuery will now retain the query. This means that a queryRef that is not consumed by useReadQuery within the given autoDisposeTimeoutMs will now be auto diposed for you.

      Thanks to #11412, disposed query refs will be automatically resubscribed to the query when consumed by useReadQuery after it has been disposed.

    • #11438 6d46ab9 Thanks @jerelmiller! - Remove the need to call retain from useBackgroundQuery since useReadQuery will now retain the query. This means that a queryRef that is not consumed by useReadQuery within the given autoDisposeTimeoutMs will now be auto diposed for you.

      Thanks to #11412, disposed query refs will be automatically resubscribed to the query when consumed by useReadQuery after it has been disposed.

    • #11175 d6d1491 Thanks @phryneas! - To work around issues in React Server Components, especially with bundling for the Next.js "edge" runtime we now use an external package to wrap react imports instead of importing React directly.

    • #11495 1190aa5 Thanks @jerelmiller! - Increase the default memory limits for executeSelectionSet and executeSelectionSetArray.

    </details>

    <details open> <summary><h3>Patch Changes</h3></summary>

    • #11275 3862f9b Thanks @phryneas! - Add a defaultContext option and property on ApolloClient, e.g. for keeping track of changing auth tokens or dependency injection.

      This can be used e.g. in authentication scenarios, where a new token might be generated outside of the link chain and should passed into the link chain.

      import { ApolloClient, createHttpLink, InMemoryCache } from "@apollo/client";
      import { setContext } from "@apollo/client/link/context";
      
      const httpLink = createHttpLink({
        uri: "/graphql",
      });
      
      const authLink = setContext((_, { headers, token }) => {
        return {
          headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : "",
          },
        };
      });
      
      const client = new ApolloClient({
        link: authLink.concat(httpLink),
        cache: new InMemoryCache(),
      });
      
      // somewhere else in your application
      function onNewToken(newToken) {
        // token can now be changed for future requests without need for a global
        // variable, scoped ref or recreating the client
        client.defaultContext.token = newToken;
      }
      
    • #11443 ff5a332 Thanks @phryneas! - Adds a deprecation warning to the HOC and render prop APIs.

      The HOC and render prop APIs have already been deprecated since 2020, but we previously didn't have a @deprecated tag in the DocBlocks.

    • #11385 d9ca4f0 Thanks @phryneas! - ensure defaultContext is also used for mutations and subscriptions

    • #11503 67f62e3 Thanks @jerelmiller! - Release changes from v3.8.10

    • #11078 14edebe Thanks @phryneas! - ObservableQuery: prevent reporting results of previous queries if the variables changed since

    • #11439 33454f0 Thanks @jerelmiller! - Address bundling issue introduced in #11412 where the react/cache internals ended up duplicated in the bundle. This was due to the fact that we had a react/hooks entrypoint that imported these files along with the newly introduced createQueryPreloader function, which lived outside of the react/hooks folder.

    • #11371 ebd8fe2 Thanks @phryneas! - Clarify types of EntityStore.makeCacheKey.

    </details>

    Open source →
  6. 3.9.0-rc.118 Jan 2024pre-release
    Release notes

    Patch Changes

    Open source →
  7. 3.9.0-rc.017 Jan 2024pre-release
    Release notes

    Minor Changes

    • #11495 1190aa5 Thanks @jerelmiller! - Increase the default memory limits for executeSelectionSet and executeSelectionSetArray.
    Open source →
  8. 3.9.0-beta.121 Dec 2023pre-release
    Release notes

    Minor Changes

    • #11424 62f3b6d Thanks @phryneas! - Simplify RetryLink, fix potential memory leak

      Historically, RetryLink would keep a values array of all previous values, in case the operation would get an additional subscriber at a later point in time. In practice, this could lead to a memory leak (#11393) and did not serve any further purpose, as the resulting observable would only be subscribed to by Apollo Client itself, and only once - it would be wrapped in a Concast before being exposed to the user, and that Concast would handle subscribers on its own.

    • #11442 4b6f2bc Thanks @jerelmiller! - Remove the need to call retain from useLoadableQuery since useReadQuery will now retain the query. This means that a queryRef that is not consumed by useReadQuery within the given autoDisposeTimeoutMs will now be auto diposed for you.

      Thanks to #11412, disposed query refs will be automatically resubscribed to the query when consumed by useReadQuery after it has been disposed.

    • #11438 6d46ab9 Thanks @jerelmiller! - Remove the need to call retain from useBackgroundQuery since useReadQuery will now retain the query. This means that a queryRef that is not consumed by useReadQuery within the given autoDisposeTimeoutMs will now be auto diposed for you.

      Thanks to #11412, disposed query refs will be automatically resubscribed to the query when consumed by useReadQuery after it has been disposed.

    Patch Changes

    • #11443 ff5a332 Thanks @phryneas! - Adds a deprecation warning to the HOC and render prop APIs.

      The HOC and render prop APIs have already been deprecated since 2020, but we previously didn't have a @deprecated tag in the DocBlocks.

    • #11078 14edebe Thanks @phryneas! - ObservableQuery: prevent reporting results of previous queries if the variables changed since

    • #11439 33454f0 Thanks @jerelmiller! - Address bundling issue introduced in #11412 where the react/cache internals ended up duplicated in the bundle. This was due to the fact that we had a react/hooks entrypoint that imported these files along with the newly introduced createQueryPreloader function, which lived outside of the react/hooks folder.

    Open source →
  9. 3.9.0-beta.018 Dec 2023pre-release
    Release notes

    Minor Changes

    • #11412 58db5c3 Thanks @jerelmiller! - Create a new useQueryRefHandlers hook that returns refetch and fetchMore functions for a given queryRef. This is useful to get access to handlers for a queryRef that was created by createQueryPreloader or when the handlers for a queryRef produced by a different component are inaccessible.

      const MyComponent({ queryRef }) {
        const { refetch, fetchMore } = useQueryRefHandlers(queryRef);
      
        // ...
      }
      
    • #11410 07fcf6a Thanks @sf-twingate! - Allow returning IGNORE sentinel object from optimisticResponse functions to bail-out from the optimistic update.

      Consider this example:

      const UPDATE_COMMENT = gql`
        mutation UpdateComment($commentId: ID!, $commentContent: String!) {
          updateComment(commentId: $commentId, content: $commentContent) {
            id
            __typename
            content
          }
        }
      `;
      
      function CommentPageWithData() {
        const [mutate] = useMutation(UPDATE_COMMENT);
        return (
          <Comment
            updateComment={({ commentId, commentContent }) =>
              mutate({
                variables: { commentId, commentContent },
                optimisticResponse: (vars, { IGNORE }) => {
                  if (commentContent === "foo") {
                    // conditionally bail out of optimistic updates
                    return IGNORE;
                  }
                  return {
                    updateComment: {
                      id: commentId,
                      __typename: "Comment",
                      content: commentContent,
                    },
                  };
                },
              })
            }
          />
        );
      }
      

      The IGNORE sentinel can be destructured from the second parameter in the callback function signature passed to optimisticResponse.

    • #11412 58db5c3 Thanks @jerelmiller! - Add the ability to start preloading a query outside React to begin fetching as early as possible. Call createQueryPreloader to create a preloadQuery function which can be called to start fetching a query. This returns a queryRef which is passed to useReadQuery and suspended until the query is done fetching.

      const preloadQuery = createQueryPreloader(client);
      const queryRef = preloadQuery(QUERY, { variables, ...otherOptions });
      
      function App() {
        return {
          <Suspense fallback={<div>Loading</div>}>
            <MyQuery />
          </Suspense>
        }
      }
      
      function MyQuery() {
        const { data } = useReadQuery(queryRef);
      
        // do something with data
      }
      
    • #11397 3f7eecb Thanks @aditya-kumawat! - Adds a new skipPollAttempt callback function that's called whenever a refetch attempt occurs while polling. If the function returns true, the refetch is skipped and not reattempted until the next poll interval. This will solve the frequent use-case of disabling polling when the window is inactive.

      useQuery(QUERY, {
        pollInterval: 1000,
        skipPollAttempt: () => document.hidden, // or !document.hasFocus()
      });
      // or define it globally
      new ApolloClient({
        defaultOptions: {
          watchQuery: {
            skipPollAttempt: () => document.hidden, // or !document.hasFocus()
          },
        },
      });
      
    • #11435 5cce53e Thanks @phryneas! - Deprecates canonizeResults.

      Using canonizeResults can result in memory leaks so we generally do not recommend using this option anymore. A future version of Apollo Client will contain a similar feature without the risk of memory leaks.

    Patch Changes

    • #11369 2a47164 Thanks @phryneas! - Persisted Query Link: improve memory management

      • use LRU WeakCache instead of WeakMap to keep a limited number of hash results
      • hash cache is initiated lazily, only when needed
      • expose persistedLink.resetHashCache() method
      • reset hash cache if the upstream server reports it doesn't accept persisted queries
    • #10804 221dd99 Thanks @phryneas! - use WeakMap in React Native with Hermes

    • #11409 2e7203b Thanks @phryneas! - Adds an experimental ApolloClient.getMemoryInternals helper

    Open source →
  10. 3.9.0-alpha.55 Dec 2023pre-release
    Release notes

    Minor Changes

    • #11345 1759066a8 Thanks @phryneas! - QueryManager.inFlightLinkObservables now uses a strong Trie as an internal data structure.

      Warning: requires @apollo/experimental-nextjs-app-support update

      If you are using @apollo/experimental-nextjs-app-support, you will need to update that to at least 0.5.2, as it accesses this internal data structure.

    • #11300 a8158733c Thanks @jerelmiller! - Introduces a new useLoadableQuery hook. This hook works similarly to useBackgroundQuery in that it returns a queryRef that can be used to suspend a component via the useReadQuery hook. It provides a more ergonomic way to load the query during a user interaction (for example when wanting to preload some data) that would otherwise be clunky with useBackgroundQuery.

      function App() {
        const [loadQuery, queryRef, { refetch, fetchMore, reset }] =
          useLoadableQuery(query, options);
      
        return (
          <>
            <button onClick={() => loadQuery(variables)}>Load query</button>
            <Suspense fallback={<SuspenseFallback />}>
              {queryRef && <Child queryRef={queryRef} />}
            </Suspense>
          </>
        );
      }
      
      function Child({ queryRef }) {
        const { data } = useReadQuery(queryRef);
      
        // ...
      }
      

    Patch Changes

    • #11356 cc4ac7e19 Thanks @phryneas! - Fix a potential memory leak in FragmentRegistry.transform and FragmentRegistry.findFragmentSpreads that would hold on to passed-in DocumentNodes for too long.

    • #11370 25e2cb431 Thanks @phryneas! - parse function: improve memory management

      • use LRU WeakCache instead of Map to keep a limited number of parsed results
      • cache is initiated lazily, only when needed
      • expose parse.resetCache() method
    • #11389 139acd115 Thanks @phryneas! - documentTransform: use optimism and WeakCache instead of directly storing data on the Trie

    • #11358 7d939f80f Thanks @phryneas! - Fixes a potential memory leak in Concast that might have been triggered when Concast was used outside of Apollo Client.

    • #11344 bd2667619 Thanks @phryneas! - Add a resetCache method to DocumentTransform and hook InMemoryCache.addTypenameTransform up to InMemoryCache.gc

    • #11367 30d17bfeb Thanks @phryneas! - print: use WeakCache instead of WeakMap

    • #11385 d9ca4f082 Thanks @phryneas! - ensure defaultContext is also used for mutations and subscriptions

    • #11387 4dce8673b Thanks @phryneas! - QueryManager.transformCache: use WeakCache instead of WeakMap

    • #11371 ebd8fe2c1 Thanks @phryneas! - Clarify types of EntityStore.makeCacheKey.

    • #11355 7d8e18493 Thanks @phryneas! - InMemoryCache.gc now also triggers FragmentRegistry.resetCaches (if there is a FragmentRegistry)

    Open source →
  11. 3.9.0-alpha.48 Nov 2023pre-release
    Release notes

    Minor Changes

    • #11175 d6d14911c Thanks @phryneas! - To work around issues in React Server Components, especially with bundling for the Next.js "edge" runtime we now use an external package to wrap react imports instead of importing React directly.

    Patch Changes

    Open source →
  12. 3.9.0-alpha.32 Nov 2023pre-release
    Release notes

    Minor Changes

    • #11301 46ab032af Thanks @alessbell! - Add multipart subscription network adapters for Relay and urql

      Relay

      import { createFetchMultipartSubscription } from "@apollo/client/utilities/subscriptions/relay";
      import { Environment, Network, RecordSource, Store } from "relay-runtime";
      
      const fetchMultipartSubs = createFetchMultipartSubscription(
        "http://localhost:4000"
      );
      
      const network = Network.create(fetchQuery, fetchMultipartSubs);
      
      export const RelayEnvironment = new Environment({
        network,
        store: new Store(new RecordSource()),
      });
      

      Urql

      import { createFetchMultipartSubscription } from "@apollo/client/utilities/subscriptions/urql";
      import { Client, fetchExchange, subscriptionExchange } from "@urql/core";
      
      const url = "http://localhost:4000";
      
      const multipartSubscriptionForwarder = createFetchMultipartSubscription(url);
      
      const client = new Client({
        url,
        exchanges: [
          fetchExchange,
          subscriptionExchange({
            forwardSubscription: multipartSubscriptionForwarder,
          }),
        ],
      });
      

    Patch Changes

    • #11275 3862f9ba9 Thanks @phryneas! - Add a defaultContext option and property on ApolloClient, e.g. for keeping track of changing auth tokens or dependency injection.

      This can be used e.g. in authentication scenarios, where a new token might be generated outside of the link chain and should passed into the link chain.

      import { ApolloClient, createHttpLink, InMemoryCache } from "@apollo/client";
      import { setContext } from "@apollo/client/link/context";
      
      const httpLink = createHttpLink({
        uri: "/graphql",
      });
      
      const authLink = setContext((_, { headers, token }) => {
        return {
          headers: {
            ...headers,
            authorization: token ? `Bearer ${token}` : "",
          },
        };
      });
      
      const client = new ApolloClient({
        link: authLink.concat(httpLink),
        cache: new InMemoryCache(),
      });
      
      // somewhere else in your application
      function onNewToken(newToken) {
        // token can now be changed for future requests without need for a global
        // variable, scoped ref or recreating the client
        client.defaultContext.token = newToken;
      }
      
    • #11297 c8c76a522 Thanks @jerelmiller! - Add an explicit return type for the useReadQuery hook called UseReadQueryResult. Previously the return type of this hook was inferred from the return value.

    Open source →
  13. 3.9.0-alpha.211 Oct 2023pre-release
    Release notes

    Patch Changes

    • #11254 d08970d34 Thanks @benjamn! - Decouple canonicalStringify from ObjectCanon for better time and memory performance.
    Open source →
  14. 3.9.0-alpha.121 Sept 2023pre-release
    Release notes

    Minor Changes

    Open source →
  15. 3.9.0-alpha.019 Sept 2023pre-release
    Release notes

    Minor Changes

    • #11202 7c2bc08b2 Thanks @benjamn! - Prevent QueryInfo#markResult mutation of result.data and return cache data consistently whether complete or incomplete.

    • #6701 8d2b4e107 Thanks @prowe! - Ability to dynamically match mocks

      Adds support for a new property MockedResponse.variableMatcher: a predicate function that accepts a variables param. If true, the variables will be passed into the ResultFunction to help dynamically build a response.

    Open source →
  16. 3.8.1018 Jan 2024
    Release notes3 sources agree

    Patch Changes

    • #11489 abfd02a Thanks @gronxb! - Fix networkStatus with useSuspenseQuery not properly updating to ready state when using a cache-and-network fetch policy that returns data equal to what is already in the cache.

    • #11483 6394dda Thanks @pipopotamasu! - Fix cache override warning output

    Open source →
  17. 3.8.99 Jan 2024
    Release notes3 sources agree

    Patch Changes

    • #11472 afc844d Thanks @alessbell! - Fix delay: Infinity when set on a MockResponse passed to Mocked Provider so it indefinitely enters loading state.

    • #11464 aac12b2 Thanks @jerelmiller! - Prevent useFragment from excessively unsubscribing and resubscribing the fragment with the cache on every render.

    • #11449 f40cda4 Thanks @phryneas! - Removes refences to the typescript "dom" lib.

    • #11470 e293bc9 Thanks @phryneas! - Remove an unnecessary check from parseAndCheckHttpResponse.

    Open source →
  18. 3.8.829 Nov 2023
    Release notes3 sources agree

    Patch Changes

    Open source →
  19. 3.8.72 Nov 2023
    Release notes

    Patch Changes

    • #11297 c8c76a522 Thanks @jerelmiller! - Add an explicit return type for the useReadQuery hook called UseReadQueryResult. Previously the return type of this hook was inferred from the return value.

    • #11337 bb1da8349 Thanks @phryneas! - #11206 used the TypeScript syntax infer X extends Y that was introduced in TS 4.8. This caused some problems for some users, so we are rolling back to a more backwards-compatible (albeit slightly less performant) type.

    Open source →
    Additional notes2 sources agree

    Patch Changes

    • #11297 c8c76a522 Thanks @jerelmiller! - Add an explicit return type for the useReadQuery hook called UseReadQueryResult. Previously the return type of this hook was inferred from the return value.

    • #11337 bb1da8349 Thanks @phryneas! - #11206 used the TypeScript syntax infer X extends Y that was introduced in TS 4.8. This caused some problems for some users, so we are rolling back to a more backwars-compatible (albeit slightly less performant) type.

    Open source →
  20. 3.8.616 Oct 2023
    Release notes3 sources agree

    Patch Changes

    • #11291 2be7eafe3 Thanks @ArioA! - Fix a bug that allows to only call loadErrorMessages without also calling loadDevErrorMessages.

    • #11274 b29f000f3 Thanks @jerelmiller! - Start the query ref auto dispose timeout after the initial promise has settled. This prevents requests that run longer than the timeout duration from keeping the component suspended indefinitely.

    • #11289 b5894dbf0 Thanks @phryneas! - MockedProvider: default connectToDevTools to false in created ApolloClient instance.

      This will prevent the mocked ApolloClient instance from trying to connect to the DevTools, which would start a setTimeout that might keep running after a test has finished.

    • #11206 dd2ce7687 Thanks @phryneas! - cache.modify: Less strict types & new dev runtime warnings.

    Open source →
  21. 3.8.55 Oct 2023
    Release notes3 sources agree

    Patch Changes

    • #11266 5192cf6e1 Thanks @phryneas! - Fixes argument handling for invariant log messages.

    • #11235 6cddaaf65 Thanks @phryneas! - Fix nextFetchPolicy behaviour with transformed documents by keeping options reference stable when passing it through QueryManager.

    • #11252 327a2abbd Thanks @phryneas! - Fixes a race condition in asyncMap that caused issues in React Native when errors were returned in the response payload along with a data property that was null.

    • #11229 c372bad4e Thanks @phryneas! - Remove (already throwing) SuspenseCache export that should have been removed in 3.8.

    • #11267 bc055e068 Thanks @phryneas! - Remove some dead code.

    Open source →
  22. 3.8.419 Sept 2023
    Release notes3 sources agree

    Patch Changes

    • #11195 9e59b251d Thanks @phryneas! - For invariant.log etc., error arguments are now serialized correctly in the link to the error page.
    Open source →
  23. 3.8.35 Sept 2023
    Release notes3 sources agree

    Patch Changes

    Open source →
  24. 3.8.21 Sept 2023
    Release notes3 sources agree

    Patch Changes

    • #10072 51045c336 Thanks @Huulivoide! - Fixes race conditions in useReactiveVar that may prevent updates to the reactive variable from propagating through the hook.

    • #11162 d9685f53c Thanks @jerelmiller! - Ensures GraphQL errors returned in subscription payloads adhere to the errorPolicy set in client.subscribe(...) calls.

    • #11134 96492e142 Thanks @alessbell! - Use separate type imports in useSuspenseQuery and useBackgroundQuery to workaround SWC compiler issue.

    • #11117 6b8198109 Thanks @phryneas! - Adds a new devtools registration mechanism and tweaks the mechanism behind the "devtools not found" mechanic.

    • #11186 f1d429f32 Thanks @jerelmiller! - Fix an issue where race conditions when rapidly switching between variables would sometimes result in the wrong data returned from the query. Specifically this occurs when a query is triggered with an initial set of variables (VariablesA), then triggers the same query with another set of variables (VariablesB) but switches back to the VariablesA before the response for VariablesB is returned. Previously this would result in the data for VariablesB to be displayed while VariablesA was active. The data is for VariablesA is now properly returned.

    • #11163 a8a9e11e9 Thanks @bignimbus! - Fix typo in error message: "occured" -> "occurred"

    • #11180 7d9c481e5 Thanks @jerelmiller! - Fixes an issue where refetching from useBackgroundQuery via refetch with an error after an error was already fetched would get stuck in a loading state.

    Open source →
  25. 3.8.110 Aug 2023
    Release notes3 sources agree

    Patch Changes

    • #11141 c469b1616 Thanks @jerelmiller! - Remove newly exported response iterator helpers that caused problems on some installs where @types/node was not available.

      IMPORTANT

      The following exports were added in version 3.8.0 that are removed with this patch.

      • isAsyncIterableIterator
      • isBlob
      • isNodeReadableStream
      • isNodeResponse
      • isReadableStream
      • isStreamableBlob
    Open source →
  26. 3.8.07 Aug 2023
    Release notes

    Minor Changes

    Fetching with Suspense 🎉

    • #10323 64cb88a4b Thanks @jerelmiller! - Add support for React suspense with a new useSuspenseQuery hook.

      useSuspenseQuery initiates a network request and causes the component calling it to suspend while the request is in flight. It can be thought of as a drop-in replacement for useQuery that allows you to take advantage of React's concurrent features while fetching during render.

      Consider a Dog component that fetches and renders some information about a dog named Mozzarella:

      <details> <summary>View code 🐶</summary>

      import { Suspense } from 'react';
      import { gql, TypedDocumentNode, useSuspenseQuery } from '@apollo/client';
      
      interface Data {
        dog: {
          id: string;
          name: string;
        };
      }
      
      interface Variables {
        name: string;
      }
      
      const GET_DOG_QUERY: TypedDocumentNode<Data, Variables> = gql`
        query GetDog($name: String) {
          dog(name: $name) {
            id
            name
          }
        }
      `;
      
      function App() {
        return (
          <Suspense fallback={<div>Loading...</div>}>
            <Dog name="Mozzarella" />
          </Suspense>
        );
      }
      
      function Dog({ name }: { name: string }) {
        const { data } = useSuspenseQuery(GET_DOG_QUERY, {
          variables: { name },
        });
      
        return <>Name: {data.dog.name}</>;
      }
      

      </details>

      For a detailed explanation of useSuspenseQuery, see our fetching with Suspense reference.

    • #10755 e3c676deb Thanks @alessbell! - Feature: adds useBackgroundQuery and useReadQuery hooks

      useBackgroundQuery initiates a request for data in a parent component and returns a QueryReference which is used to read the data in a child component via useReadQuery. If the child component attempts to render before the data can be found in the cache, the child component will suspend until the data is available. On cache updates to watched data, the child component calling useReadQuery will re-render with new data but the parent component will not re-render (as it would, for example, if it were using useQuery to issue the request).

      Consider an App component that fetches a list of breeds in the background while also fetching and rendering some information about an individual dog, Mozzarella:

      <details> <summary>View code 🐶</summary>

      function App() {
        const [queryRef] = useBackgroundQuery(GET_BREEDS_QUERY);
        return (
          <Suspense fallback={<div>Loading...</div>}>
            <Dog name="Mozzarella" queryRef={queryRef} />
          </Suspense>
        );
      }
      
      function Dog({
        name,
        queryRef,
      }: {
        name: string;
        queryRef: QueryReference<BreedData>;
      }) {
        const { data } = useSuspenseQuery(GET_DOG_QUERY, {
          variables: { name },
        });
        return (
          <>
            Name: {data.dog.name}
            <Suspense fallback={<div>Loading breeds...</div>}>
              <Breeds queryRef={queryRef} />
            </Suspense>
          </>
        );
      }
      
      function Breeds({ queryRef }: { queryRef: QueryReference<BreedData> }) {
        const { data } = useReadQuery(queryRef);
        return data.breeds.map(({ characteristics }) =>
          characteristics.map((characteristic) => (
            <div key={characteristic}>{characteristic}</div>
          ))
        );
      }
      

      </details>

      For a detailed explanation of useBackgroundQuery and useReadQuery, see our fetching with Suspense reference.

    Document transforms 📑

    • #10509 79df2c7ba Thanks @jerelmiller! - Add the ability to specify custom GraphQL document transforms. These transforms are run before reading data from the cache, before local state is resolved, and before the query document is sent through the link chain.

      To register a custom document transform, create a transform using the DocumentTransform class and pass it to the documentTransform option on ApolloClient.

      import { DocumentTransform } from "@apollo/client";
      
      const documentTransform = new DocumentTransform((document) => {
        // do something with `document`
        return transformedDocument;
      });
      
      const client = new ApolloClient({ documentTransform: documentTransform });
      

      For more information on the behavior and API of DocumentTransform, see its reference page in our documentation.

    New removeTypenameFromVariables link 🔗

    • #10853 300957960 Thanks @jerelmiller! - Introduce the new removeTypenameFromVariables link. This link will automatically remove __typename fields from variables for all operations. This link can be configured to exclude JSON-scalars for scalars that utilize __typename.

      This change undoes some work from #10724 where __typename was automatically stripped for all operations with no configuration. This was determined to be a breaking change and therefore moved into this link.

      For a detailed explanation of removeTypenameFromVariables, see its API reference.

    New skipToken sentinel ⏭️

    • #11112 b4aefcfe9 Thanks @jerelmiller! - Adds support for a skipToken sentinel that can be used as options in useSuspenseQuery and useBackgroundQuery to skip execution of a query. This works identically to the skip option but is more type-safe and as such, becomes the recommended way to skip query execution. As such, the skip option has been deprecated in favor of skipToken.

      We are considering the removal of the skip option from useSuspenseQuery and useBackgroundQuery in the next major. We are releasing with it now to make migration from useQuery easier and make skipToken more discoverable.

      useSuspenseQuery

      import { skipToken, useSuspenseQuery } from "@apollo/client";
      
      const id: number | undefined;
      
      const { data } = useSuspenseQuery(
        query,
        id ? { variables: { id } } : skipToken
      );
      

      useBackgroundQuery

      import { skipToken, useBackgroundQuery } from '@apollo/client';
      
      function Parent() {
        const [queryRef] = useBackgroundQuery(
          query,
          id ? { variables: { id } } : skipToken
        );
      
        return queryRef ? <Child queryRef={queryRef} /> : null;
      }
      
      function Child({ queryRef }: { queryRef: QueryReference<TData> }) {
        const { data } = useReadQuery(queryRef);
      }
      

      For a detailed explanation of skipToken, see its API reference.

    New error extraction mechanism, smaller bundles 📉

    • #10887 f8c0b965d Thanks @phryneas! - Add a new mechanism for Error Extraction to reduce bundle size by including error message texts on an opt-in basis.

      By default, errors will link to an error page with the entire error message. This replaces "development" and "production" errors and works without additional bundler configuration.

      Bundling the text of error messages and development warnings can be enabled as follows:

      import { loadErrorMessages, loadDevMessages } from "@apollo/client/dev";
      if (process.env.NODE_ENV !== "production") {
        loadErrorMessages();
        loadDevMessages();
      }
      

      For a detailed explanation, see our reference on reducing bundle size.

    New @nonreactive directive 🎬

    • #10722 c7e60f83d Thanks @benjamn! - Implement a @nonreactive directive for selectively skipping reactive comparisons of query result subtrees.

      The @nonreactive directive can be used to mark query fields or fragment spreads and is used to indicate that changes to the data contained within the subtrees marked @nonreactive should not trigger re-rendering. This allows parent components to fetch data to be rendered by their children without re-rendering themselves when the data corresponding with fields marked as @nonreactive change.

      Consider an App component that fetches and renders a list of ski trails:

      <details> <summary>View code 🎿</summary>

      const TrailFragment = gql`
        fragment TrailFragment on Trail {
          name
          status
        }
      `;
      
      const ALL_TRAILS = gql`
        query allTrails {
          allTrails {
            id
            ...TrailFragment @nonreactive
          }
        }
        ${TrailFragment}
      `;
      
      function App() {
        const { data, loading } = useQuery(ALL_TRAILS);
        return (
          <main>
            <h2>Ski Trails</h2>
            <ul>
              {data?.trails.map((trail) => (
                <Trail key={trail.id} id={trail.id} />
              ))}
            </ul>
          </main>
        );
      }
      

      </details>

      The Trail component renders a trail's name and status and allows the user to execute a mutation to toggle the status of the trail between "OPEN" and "CLOSED":

      <details> <summary>View code 🎿</summary>

      const Trail = ({ id }) => {
        const [updateTrail] = useMutation(UPDATE_TRAIL);
        const { data } = useFragment({
          fragment: TrailFragment,
          from: {
            __typename: "Trail",
            id,
          },
        });
        return (
          <li key={id}>
            {data.name} - {data.status}
            <input
              checked={data.status === "OPEN" ? true : false}
              type="checkbox"
              onChange={(e) => {
                updateTrail({
                  variables: {
                    trailId: id,
                    status: e.target.checked ? "OPEN" : "CLOSED",
                  },
                });
              }}
            />
          </li>
        );
      };
      

      </details>

      Notice that the Trail component isn't receiving the entire trail object via props, only the id which is used along with the fragment document to create a live binding for each trail item in the cache. This allows each Trail component to react to the cache updates for a single trail independently. Updates to a trail's status will not cause the parent App component to rerender since the @nonreactive directive is applied to the TrailFragment spread, a fragment that includes the status field.

      For a detailed explanation, see our @nonreactive reference and @alessbell's post on the Apollo blog about using @nonreactive with useFragment.

    Abort the AbortController signal more granularly 🛑

    • #11040 125ef5b2a Thanks @phryneas! - HttpLink/BatchHttpLink: Abort the AbortController signal more granularly.

      Before this change, when HttpLink/BatchHttpLink created an AbortController internally, the signal would always be .aborted after the request was completed. This could cause issues with Sentry Session Replay and Next.js App Router Cache invalidations, which just replayed the fetch with the same options - including the cancelled AbortSignal.

      With this change, the AbortController will only be .abort()ed by outside events, not as a consequence of the request completing.

    useFragment drops its experimental label 🎓

    • #10916 ea75e18de Thanks @alessbell! - Remove experimental labels.

      useFragment, introduced in 3.7.0 as useFragment_experimental, is no longer an experimental API 🎉 We've removed the _experimental suffix from its named export and have made a number of improvements.

      For a detailed explanation, see our useFragment reference and @alessbell's post on the Apollo blog about using useFragment with @nonreactive for improved performance when rendering lists.

      <details> <summary><h5><code>useFragment</code> improvements</h5></summary>

      • #10765 35f36c5aa Thanks @phryneas! - More robust types for the data property on UseFragmentResult. When a partial result is given, the type is now correctly set to Partial<TData>.

      • #11083 f766e8305 Thanks @phryneas! - Adjust the rerender timing of useQuery to more closely align with useFragment. This means that cache updates delivered to both hooks should trigger renders at relatively the same time. Previously, the useFragment might rerender much faster leading to some confusion.

      • #10836 6794893c2 Thanks @phryneas! - Remove the deprecated returnPartialData option from useFragment hook.

      </details>

    <details open> <summary><h4>More Minor Changes</h4></summary>

    • #10895 e187866fd Thanks @Gelio! - Add generic type parameter for the entity modified in cache.modify. Improves TypeScript type inference for that type's fields and values of those fields.

      Example:

      cache.modify<Book>({
        id: cache.identify(someBook),
        fields: {
          title: (title) => {
            // title has type `string`.
            // It used to be `any`.
          },
       => {
            // author has type `Reference | Book["author"]`.
            // It used to be `any`.
          },
        },
      });
      
    • #10895 e187866fd Thanks @Gelio! - Use unique opaque types for the DELETE and INVALIDATE Apollo cache modifiers.

      This increases type safety, since these 2 modifiers no longer have the any type. Moreover, it no longer triggers the @typescript-eslint/no-unsafe-return rule.

    • #10340 4f73c5ca1 Thanks @alessbell! - Avoid calling useQuery onCompleted for cache writes

    • #10527 0cc7e2e19 Thanks @phryneas! - Remove the query/mutation/subscription option from hooks that already take that value as their first argument.

    • #10506 2dc2e1d4f Thanks @phryneas! - prevent accidental widening of inferred TData and TVariables generics for query hook option arguments

    • #10521 fbf729414 Thanks @benjamn! - Simplify __DEV__ polyfill to use imports instead of global scope

    • #10994 2ebbd3abb Thanks @phryneas! - Add .js file extensions to imports in src and dist/*/.d.ts

    • #11045 9c1d4a104 Thanks @jerelmiller! - When changing variables back to a previously used set of variables, do not automatically cache the result as part of the query reference. Instead, dispose of the query reference so that the InMemoryCache can determine the cached behavior. This means that fetch policies that would guarantee a network request are now honored when switching back to previously used variables.

    • #11058 89bf33c42 Thanks @phryneas! - (Batch)HttpLink: Propagate AbortErrors to the user when a user-provided signal is passed to the link. Previously, these links would swallow all AbortErrors, potentially causing queries and mutations to never resolve. As a result of this change, users are now expected to handle AbortErrors when passing in a user-provided signal.

    • #10346 3bcfc42d3 Thanks @jerelmiller! - Add the ability to allow @client fields to be sent to the link chain.

    • #10567 c2ce6496c Thanks @benjamn! - Allow ApolloCache implementations to specify default value for assumeImmutableResults client option, improving performance for applications currently using InMemoryCache without configuring new ApolloClient({ assumeImmutableResults: true })

    • #10915 3a62d8228 Thanks @phryneas! - Changes how development-only code is bundled in the library to more reliably enable consuming bundlers to reduce production bundle sizes while keeping compatibility with non-node environments.

    </details>

    <details open> <summary><h3>Patch Changes</h3></summary>

    • #11086 0264fee06 Thanks @jerelmiller! - Fix an issue where a call to refetch, fetchMore, or changing skip to false that returned a result deeply equal to data in the cache would get stuck in a pending state and never resolve.

    • #11053 c0ca70720 Thanks @phryneas! - Add SuspenseCache as a lazy hidden property on ApolloClient. This means that SuspenseCache is now an implementation details of Apollo Client and you no longer need to manually instantiate it and no longer need to pass it into ApolloProvider. Trying to instantiate a SuspenseCache instance in your code will now throw an error.

    • #11115 78739e3ef Thanks @phryneas! - Enforce export type for all type-level exports.

    • #11027 e47cfd04e Thanks @phryneas! - Prevents the DevTool installation warning to be turned into a documentation link.

    • #10594 f221b5e8f Thanks @phryneas! - Add a suspenseCache option to useSuspenseQuery

    • #10700 12e37f46f Thanks @jerelmiller! - Add a queryKey option to useSuspenseQuery that allows the hook to create a unique subscription instance.

    • #10724 e285dfd00 Thanks @jerelmiller! - Automatically strips __typename fields from variables sent to the server when using HttpLink, BatchHttpLink, or GraphQLWsLink. This allows GraphQL data returned from a query to be used as an argument to a subsequent GraphQL operation without the need to strip the __typename in user-space.

    • #10957 445164d21 Thanks @phryneas! - Use React.version as key for shared Contexts.

    • #10635 7df51ee19 Thanks @jerelmiller! - Fix an issue where cache updates would not propagate to useSuspenseQuery while in strict mode.

    • #11013 5ed2cfdaf Thanks @alessbell! - Make private fields inFlightLinkObservables and fetchCancelFns protected in QueryManager in order to make types available in @apollo/experimental-nextjs-app-support package when extending the ApolloClient class.

    • #10869 ba1d06166 Thanks @phryneas! - Ensure Context value stability when rerendering ApolloProvider with the same client and/or suspenseCache prop

    • #11103 e3d611daf Thanks @caylahamann! - Fixes a bug in useMutation so that onError is called when an error is returned from the request with errorPolicy set to 'all' .

    • #10657 db305a800 Thanks @jerelmiller! - Return networkStatus in the useSuspenseQuery result.

    • #10937 eea44eb87 Thanks @jerelmiller! - Moves DocumentTransform to the utilities sub-package to avoid a circular dependency between the core and cache sub-packages.

    • #10951 2e833b2ca Thanks @alessbell! - Improve useBackgroundQuery type interface

    • #10651 8355d0e1e Thanks @jerelmiller! - Fixes an issue where useSuspenseQuery would not respond to cache updates when using a cache-first fetchPolicy after the hook was mounted with data already in the cache.

    • #11026 b8d405eee Thanks @phryneas! - Store React.Context instance mapped by React.createContext instance, not React.version. Using React.version can cause problems with preact, as multiple versions of preact will all identify themselves as React 17.0.2.

    • #11000 1d43ab616 Thanks @phryneas! - Use import * as React everywhere. This prevents an error when importing @apollo/client in a React Server component. (see #10974)

    • #10852 27fbdb3f9 Thanks @phryneas! - Chore: Add ESLint rule for consistent type imports, apply autofix

    • #10999 c1904a78a Thanks @phryneas! - Fix a bug in QueryReference where this.resolve or this.reject might be executed even if undefined.

    • #10940 1d38f128f Thanks @jerelmiller! - Add support for the skip option in useBackgroundQuery and useSuspenseQuery. Setting this option to true will avoid a network request.

    • #10672 932252b0c Thanks @jerelmiller! - Fix the compatibility between useSuspenseQuery and React's useDeferredValue and startTransition APIs to allow React to show stale UI while the changes to the variable cause the component to suspend.

      Breaking change

      nextFetchPolicy support has been removed from useSuspenseQuery. If you are using this option, remove it, otherwise it will be ignored.

    • #10964 f33171506 Thanks @alessbell! - Fixes a bug in BatchHttpLink that removed variables from all requests by default.

    • #10633 90a06eeeb Thanks @benjamn! - Fix type policy inheritance involving fuzzy possibleTypes

    • #10754 64b304862 Thanks @sincraianul! - Fix includeUnusedVariables option not working with BatchHttpLink

    • #11018 5618953f3 Thanks @jerelmiller! - useBackgroundQuery now uses its own options type called BackgroundQueryHookOptions rather than reusing SuspenseQueryHookOptions.

    • #11035 a3ab7456d Thanks @jerelmiller! - Incrementally re-render deferred queries after calling refetch or setting skip to false to match the behavior of the initial fetch. Previously, the hook would not re-render until the entire result had finished loading in these cases.

    • #10399 652a1ae08 Thanks @alessbell! - Silence useLayoutEffect warning when useSuspenseQuery runs on server

    • #10919 f796ce1ac Thanks @jerelmiller! - Fix an issue when using a link that relied on operation.getContext and operation.setContext would error out when it was declared after the removeTypenameFromVariables link.

    • #10968 b102390b2 Thanks @phryneas! - Use printed query for query deduplication. Cache print calls for GraphQL documents to speed up repeated operations.

    • #11071 4473e925a Thanks @jerelmiller! - #10509 introduced some helpers for determining the type of operation for a GraphQL query. This imported the OperationTypeNode from graphql-js which is not available in GraphQL 14. To maintain compatibility with graphql-js v14, this has been reverted to use plain strings.

    • #10766 ffb179e55 Thanks @jerelmiller! - More robust typings for the data property returned from useSuspenseQuery when using returnPartialData: true or an errorPolicy of all or ignore. TData now defaults to unknown instead of any.

    • #10401 3e5b41a75 Thanks @jerelmiller! - Always throw network errors in useSuspenseQuery regardless of the set errorPolicy.

    • #10877 f40248598 Thanks @phryneas! - Change an import in useQuery and useMutation that added an unnecessary runtime dependency on @apollo/client/core. This drastically reduces the bundle size of each the hooks.

    • #10656 54c4d2f3c Thanks @jerelmiller! - Ensure refetch, fetchMore, and subscribeToMore functions returned by useSuspenseQuery are referentially stable between renders, even as data is updated.

    • #10324 95eb228be Thanks @jerelmiller! - Add @defer support to useSuspenseQuery.

    • #10888 1562a2f5a Thanks @alessbell! - Updates dependency versions in package.json by bumping:

      • @wry/context to ^0.7.3
      • @wry/equality to ^0.5.6
      • @wry/trie to ^0.4.3
      • optimism to ^0.17.4

      to 1. fix sourcemap warnings and 2. a Codesandbox sandpack (in-browser) bundler transpilation bug with an upstream optimism workaround.

    • #11010 1051a9c88 Thanks @alessbell! - Hide queryRef in a Symbol in useBackgroundQuerys return value.

    • #10758 9def7421f Thanks @phryneas! - use React.use where available

    • #11032 6a4da900a Thanks @jerelmiller! - Throw errors in useSuspenseQuery for errors returned in incremental chunks when errorPolicy is none. This provides a more consistent behavior of the errorPolicy in the hook.

      Potentially breaking change

      Previously, if you issued a query with @defer and relied on errorPolicy: 'none' to set the error property returned from useSuspenseQuery when the error was returned in an incremental chunk, this error is now thrown. Switch the errorPolicy to all to avoid throwing the error and instead return it in the error property.

    • #10960 ee407ef97 Thanks @alessbell! - Adds support for returnPartialData and refetchWritePolicy options in useBackgroundQuery hook.

    • #10809 49d28f764 Thanks @jerelmiller! - Fixed the ability to use refetch and fetchMore with React's startTransition. The hook will now behave correctly by allowing React to avoid showing the Suspense fallback when these functions are wrapped by startTransition. This change deprecates the suspensePolicy option in favor of startTransition.

    • #11082 0f1cde3a2 Thanks @phryneas! - Restore Apollo Client 3.7 getApolloContext behaviour

    • #10969 525a9317a Thanks @phryneas! - Slightly decrease bundle size and memory footprint of SuspenseCache by changing how cache entries are stored internally.

    • #11025 6092b6edf Thanks @jerelmiller! - useSuspenseQuery and useBackgroundQuery will now properly apply changes to its options between renders.

    • #10872 96b4f8837 Thanks @phryneas! - The "per-React-Version-Singleton" ApolloContext is now stored on globalThis, not React.createContext, and throws an error message when accessed from React Server Components.

    • #10450 f8bc33387 Thanks @jerelmiller! - Add support for the subscribeToMore and client fields returned in the useSuspenseQuery result.

    </details>

    Open source →
    Additional notes2 sources agree

    Minor Changes

    Fetching with Suspense 🎉

    • #10323 64cb88a4b Thanks @jerelmiller! - Add support for React suspense with a new useSuspenseQuery hook.

      useSuspenseQuery initiates a network request and causes the component calling it to suspend while the request is in flight. It can be thought of as a drop-in replacement for useQuery that allows you to take advantage of React's concurrent features while fetching during render.

      Consider a Dog component that fetches and renders some information about a dog named Mozzarella:

      <details> <summary>View code 🐶</summary>

      import { Suspense } from "react";
      import { gql, TypedDocumentNode, useSuspenseQuery } from "@apollo/client";
      
      interface Data {
        dog: {
          id: string;
          name: string;
        };
      }
      
      interface Variables {
        name: string;
      }
      
      const GET_DOG_QUERY: TypedDocumentNode<Data, Variables> = gql`
        query GetDog($name: String) {
          dog(name: $name) {
            id
            name
          }
        }
      `;
      
      function App() {
        return (
          <Suspense fallback={<div>Loading...</div>}>
            <Dog name="Mozzarella" />
          </Suspense>
        );
      }
      
      function Dog({ name }: { name: string }) {
        const { data } = useSuspenseQuery(GET_DOG_QUERY, {
          variables: { name },
        });
      
        return <>Name: {data.dog.name}</>;
      }
      

      </details>

      For a detailed explanation of useSuspenseQuery, see our fetching with Suspense reference.

    • #10755 e3c676deb Thanks @alessbell! - Feature: adds useBackgroundQuery and useReadQuery hooks

      useBackgroundQuery initiates a request for data in a parent component and returns a QueryReference which is used to read the data in a child component via useReadQuery. If the child component attempts to render before the data can be found in the cache, the child component will suspend until the data is available. On cache updates to watched data, the child component calling useReadQuery will re-render with new data but the parent component will not re-render (as it would, for example, if it were using useQuery to issue the request).

      Consider an App component that fetches a list of breeds in the background while also fetching and rendering some information about an individual dog, Mozzarella:

      <details> <summary>View code 🐶</summary>

      function App() {
        const [queryRef] = useBackgroundQuery(GET_BREEDS_QUERY);
        return (
          <Suspense fallback={<div>Loading...</div>}>
            <Dog name="Mozzarella" queryRef={queryRef} />
          </Suspense>
        );
      }
      
      function Dog({
        name,
        queryRef,
      }: {
        name: string;
        queryRef: QueryReference<BreedData>;
      }) {
        const { data } = useSuspenseQuery(GET_DOG_QUERY, {
          variables: { name },
        });
        return (
          <>
            Name: {data.dog.name}
            <Suspense fallback={<div>Loading breeds...</div>}>
              <Breeds queryRef={queryRef} />
            </Suspense>
          </>
        );
      }
      
      function Breeds({ queryRef }: { queryRef: QueryReference<BreedData> }) {
        const { data } = useReadQuery(queryRef);
        return data.breeds.map(({ characteristics }) =>
          characteristics.map((characteristic) => (
            <div key={characteristic}>{characteristic}</div>
          ))
        );
      }
      

      </details>

      For a detailed explanation of useBackgroundQuery and useReadQuery, see our fetching with Suspense reference.

    Document transforms 📑

    • #10509 79df2c7ba Thanks @jerelmiller! - Add the ability to specify custom GraphQL document transforms. These transforms are run before reading data from the cache, before local state is resolved, and before the query document is sent through the link chain.

      To register a custom document transform, create a transform using the DocumentTransform class and pass it to the documentTransform option on ApolloClient.

      import { DocumentTransform } from "@apollo/client";
      
      const documentTransform = new DocumentTransform((document) => {
        // do something with `document`
        return transformedDocument;
      });
      
      const client = new ApolloClient({ documentTransform: documentTransform });
      

      For more information on the behavior and API of DocumentTransform, see its reference page in our documentation.

    New removeTypenameFromVariables link 🔗

    • #10853 300957960 Thanks @jerelmiller! - Introduce the new removeTypenameFromVariables link. This link will automatically remove __typename fields from variables for all operations. This link can be configured to exclude JSON-scalars for scalars that utilize __typename.

      This change undoes some work from #10724 where __typename was automatically stripped for all operations with no configuration. This was determined to be a breaking change and therefore moved into this link.

      For a detailed explanation of removeTypenameFromVariables, see its API reference.

    New skipToken sentinel ⏭️

    • #11112 b4aefcfe9 Thanks @jerelmiller! - Adds support for a skipToken sentinel that can be used as options in useSuspenseQuery and useBackgroundQuery to skip execution of a query. This works identically to the skip option but is more type-safe and as such, becomes the recommended way to skip query execution. As such, the skip option has been deprecated in favor of skipToken.

      We are considering the removal of the skip option from useSuspenseQuery and useBackgroundQuery in the next major. We are releasing with it now to make migration from useQuery easier and make skipToken more discoverable.

      useSuspenseQuery

      import { skipToken, useSuspenseQuery } from "@apollo/client";
      
      const id: number | undefined;
      
      const { data } = useSuspenseQuery(
        query,
        id ? { variables: { id } } : skipToken
      );
      

      useBackgroundQuery

      import { skipToken, useBackgroundQuery } from "@apollo/client";
      
      function Parent() {
        const [queryRef] = useBackgroundQuery(
          query,
          id ? { variables: { id } } : skipToken
        );
      
        return queryRef ? <Child queryRef={queryRef} /> : null;
      }
      
      function Child({ queryRef }: { queryRef: QueryReference<TData> }) {
        const { data } = useReadQuery(queryRef);
      }
      

      For a detailed explanation of skipToken, see its API reference.

    New error extraction mechanism, smaller bundles 📉

    • #10887 f8c0b965d Thanks @phryneas! - Add a new mechanism for Error Extraction to reduce bundle size by including error message texts on an opt-in basis.

      By default, errors will link to an error page with the entire error message. This replaces "development" and "production" errors and works without additional bundler configuration.

      Bundling the text of error messages and development warnings can be enabled as follows:

      import { loadErrorMessages, loadDevMessages } from "@apollo/client/dev";
      if (process.env.NODE_ENV !== "production") {
        loadErrorMessages();
        loadDevMessages();
      }
      

      For a detailed explanation, see our reference on reducing bundle size.

    New @nonreactive directive 🎬

    • #10722 c7e60f83d Thanks @benjamn! - Implement a @nonreactive directive for selectively skipping reactive comparisons of query result subtrees.

      The @nonreactive directive can be used to mark query fields or fragment spreads and is used to indicate that changes to the data contained within the subtrees marked @nonreactive should not trigger re-rendering. This allows parent components to fetch data to be rendered by their children without re-rendering themselves when the data corresponding with fields marked as @nonreactive change.

      Consider an App component that fetches and renders a list of ski trails:

      <details> <summary>View code 🎿</summary>

      const TrailFragment = gql`
        fragment TrailFragment on Trail {
          name
          status
        }
      `;
      
      const ALL_TRAILS = gql`
        query allTrails {
          allTrails {
            id
            ...TrailFragment @nonreactive
          }
        }
        ${TrailFragment}
      `;
      
      function App() {
        const { data, loading } = useQuery(ALL_TRAILS);
        return (
          <main>
            <h2>Ski Trails</h2>
            <ul>
              {data?.trails.map((trail) => (
                <Trail key={trail.id} id={trail.id} />
              ))}
            </ul>
          </main>
        );
      }
      

      </details>

      The Trail component renders a trail's name and status and allows the user to execute a mutation to toggle the status of the trail between "OPEN" and "CLOSED":

      <details> <summary>View code 🎿</summary>

      const Trail = ({ id }) => {
        const [updateTrail] = useMutation(UPDATE_TRAIL);
        const { data } = useFragment({
          fragment: TrailFragment,
          from: {
            __typename: "Trail",
            id,
          },
        });
        return (
          <li key={id}>
            {data.name} - {data.status}
            <input
              checked={data.status === "OPEN" ? true : false}
              type="checkbox"
              onChange={(e) => {
                updateTrail({
                  variables: {
                    trailId: id,
                    status: e.target.checked ? "OPEN" : "CLOSED",
                  },
                });
              }}
            />
          </li>
        );
      };
      

      </details>

      Notice that the Trail component isn't receiving the entire trail object via props, only the id which is used along with the fragment document to create a live binding for each trail item in the cache. This allows each Trail component to react to the cache updates for a single trail independently. Updates to a trail's status will not cause the parent App component to rerender since the @nonreactive directive is applied to the TrailFragment spread, a fragment that includes the status field.

      For a detailed explanation, see our @nonreactive reference and @alessbell's post on the Apollo blog about using @nonreactive with useFragment.

    Abort the AbortController signal more granularly 🛑

    • #11040 125ef5b2a Thanks @phryneas! - HttpLink/BatchHttpLink: Abort the AbortController signal more granularly.

      Before this change, when HttpLink/BatchHttpLink created an AbortController internally, the signal would always be .aborted after the request was completed. This could cause issues with Sentry Session Replay and Next.js App Router Cache invalidations, which just replayed the fetch with the same options - including the cancelled AbortSignal.

      With this change, the AbortController will only be .abort()ed by outside events, not as a consequence of the request completing.

    useFragment drops its experimental label 🎓

    • #10916 ea75e18de Thanks @alessbell! - Remove experimental labels.

      useFragment, introduced in 3.7.0 as useFragment_experimental, is no longer an experimental API 🎉 We've removed the _experimental suffix from its named export and have made a number of improvements.

      For a detailed explanation, see our useFragment reference and @alessbell's post on the Apollo blog about using useFragment with @nonreactive for improved performance when rendering lists.

      <details> <summary><h5><code>useFragment</code> improvements</h5></summary>

      • #10765 35f36c5aa Thanks @phryneas! - More robust types for the data property on UseFragmentResult. When a partial result is given, the type is now correctly set to Partial<TData>.

      • #11083 f766e8305 Thanks @phryneas! - Adjust the rerender timing of useQuery to more closely align with useFragment. This means that cache updates delivered to both hooks should trigger renders at relatively the same time. Previously, the useFragment might rerender much faster leading to some confusion.

      • #10836 6794893c2 Thanks @phryneas! - Remove the deprecated returnPartialData option from useFragment hook.

      </details>

    <details open> <summary><h4>More Minor Changes</h4></summary>

    • #10895 e187866fd Thanks @Gelio! - Add generic type parameter for the entity modified in cache.modify. Improves TypeScript type inference for that type's fields and values of those fields.

      Example:

      cache.modify<Book>({
        id: cache.identify(someBook),
        fields: {
          title: (title) => {
            // title has type `string`.
            // It used to be `any`.
          },
       => {
            // author has type `Reference | Book["author"]`.
            // It used to be `any`.
          },
        },
      });
      
    • #10895 e187866fd Thanks @Gelio! - Use unique opaque types for the DELETE and INVALIDATE Apollo cache modifiers.

      This increases type safety, since these 2 modifiers no longer have the any type. Moreover, it no longer triggers the @typescript-eslint/no-unsafe-return rule.

    • #10340 4f73c5ca1 Thanks @alessbell! - Avoid calling useQuery onCompleted for cache writes

    • #10527 0cc7e2e19 Thanks @phryneas! - Remove the query/mutation/subscription option from hooks that already take that value as their first argument.

    • #10506 2dc2e1d4f Thanks @phryneas! - prevent accidental widening of inferred TData and TVariables generics for query hook option arguments

    • #10521 fbf729414 Thanks @benjamn! - Simplify __DEV__ polyfill to use imports instead of global scope

    • #10994 2ebbd3abb Thanks @phryneas! - Add .js file extensions to imports in src and dist/*/.d.ts

    • #11045 9c1d4a104 Thanks @jerelmiller! - When changing variables back to a previously used set of variables, do not automatically cache the result as part of the query reference. Instead, dispose of the query reference so that the InMemoryCache can determine the cached behavior. This means that fetch policies that would guarantee a network request are now honored when switching back to previously used variables.

    • #11058 89bf33c42 Thanks @phryneas! - (Batch)HttpLink: Propagate AbortErrors to the user when a user-provided signal is passed to the link. Previously, these links would swallow all AbortErrors, potentially causing queries and mutations to never resolve. As a result of this change, users are now expected to handle AbortErrors when passing in a user-provided signal.

    • #10346 3bcfc42d3 Thanks @jerelmiller! - Add the ability to allow @client fields to be sent to the link chain.

    • #10567 c2ce6496c Thanks @benjamn! - Allow ApolloCache implementations to specify default value for assumeImmutableResults client option, improving performance for applications currently using InMemoryCache without configuring new ApolloClient({ assumeImmutableResults: true })

    • #10915 3a62d8228 Thanks @phryneas! - Changes how development-only code is bundled in the library to more reliably enable consuming bundlers to reduce production bundle sizes while keeping compatibility with non-node environments.

    </details>

    <details open> <summary><h3>Patch Changes</h3></summary>

    • #11086 0264fee06 Thanks @jerelmiller! - Fix an issue where a call to refetch, fetchMore, or changing skip to false that returned a result deeply equal to data in the cache would get stuck in a pending state and never resolve.

    • #11053 c0ca70720 Thanks @phryneas! - Add SuspenseCache as a lazy hidden property on ApolloClient. This means that SuspenseCache is now an implementation details of Apollo Client and you no longer need to manually instantiate it and no longer need to pass it into ApolloProvider. Trying to instantiate a SuspenseCache instance in your code will now throw an error.

    • #11115 78739e3ef Thanks @phryneas! - Enforce export type for all type-level exports.

    • #11027 e47cfd04e Thanks @phryneas! - Prevents the DevTool installation warning to be turned into a documentation link.

    • #10594 f221b5e8f Thanks @phryneas! - Add a suspenseCache option to useSuspenseQuery

    • #10700 12e37f46f Thanks @jerelmiller! - Add a queryKey option to useSuspenseQuery that allows the hook to create a unique subscription instance.

    • #10724 e285dfd00 Thanks @jerelmiller! - Automatically strips __typename fields from variables sent to the server when using HttpLink, BatchHttpLink, or GraphQLWsLink. This allows GraphQL data returned from a query to be used as an argument to a subsequent GraphQL operation without the need to strip the __typename in user-space.

    • #10957 445164d21 Thanks @phryneas! - Use React.version as key for shared Contexts.

    • #10635 7df51ee19 Thanks @jerelmiller! - Fix an issue where cache updates would not propagate to useSuspenseQuery while in strict mode.

    • #11013 5ed2cfdaf Thanks @alessbell! - Make private fields inFlightLinkObservables and fetchCancelFns protected in QueryManager in order to make types available in @apollo/experimental-nextjs-app-support package when extending the ApolloClient class.

    • #10869 ba1d06166 Thanks @phryneas! - Ensure Context value stability when rerendering ApolloProvider with the same client and/or suspenseCache prop

    • #11103 e3d611daf Thanks @caylahamann! - Fixes a bug in useMutation so that onError is called when an error is returned from the request with errorPolicy set to 'all' .

    • #10657 db305a800 Thanks @jerelmiller! - Return networkStatus in the useSuspenseQuery result.

    • #10937 eea44eb87 Thanks @jerelmiller! - Moves DocumentTransform to the utilities sub-package to avoid a circular dependency between the core and cache sub-packages.

    • #10951 2e833b2ca Thanks @alessbell! - Improve useBackgroundQuery type interface

    • #10651 8355d0e1e Thanks @jerelmiller! - Fixes an issue where useSuspenseQuery would not respond to cache updates when using a cache-first fetchPolicy after the hook was mounted with data already in the cache.

    • #11026 b8d405eee Thanks @phryneas! - Store React.Context instance mapped by React.createContext instance, not React.version. Using React.version can cause problems with preact, as multiple versions of preact will all identify themselves as React 17.0.2.

    • #11000 1d43ab616 Thanks @phryneas! - Use import * as React everywhere. This prevents an error when importing @apollo/client in a React Server component. (see #10974)

    • #10852 27fbdb3f9 Thanks @phryneas! - Chore: Add ESLint rule for consistent type imports, apply autofix

    • #10999 c1904a78a Thanks @phryneas! - Fix a bug in QueryReference where this.resolve or this.reject might be executed even if undefined.

    • #10940 1d38f128f Thanks @jerelmiller! - Add support for the skip option in useBackgroundQuery and useSuspenseQuery. Setting this option to true will avoid a network request.

    • #10672 932252b0c Thanks @jerelmiller! - Fix the compatibility between useSuspenseQuery and React's useDeferredValue and startTransition APIs to allow React to show stale UI while the changes to the variable cause the component to suspend.

      Breaking change

      nextFetchPolicy support has been removed from useSuspenseQuery. If you are using this option, remove it, otherwise it will be ignored.

    • #10964 f33171506 Thanks @alessbell! - Fixes a bug in BatchHttpLink that removed variables from all requests by default.

    • #10633 90a06eeeb Thanks @benjamn! - Fix type policy inheritance involving fuzzy possibleTypes

    • #10754 64b304862 Thanks @sincraianul! - Fix includeUnusedVariables option not working with BatchHttpLink

    • #11018 5618953f3 Thanks @jerelmiller! - useBackgroundQuery now uses its own options type called BackgroundQueryHookOptions rather than reusing SuspenseQueryHookOptions.

    • #11035 a3ab7456d Thanks @jerelmiller! - Incrementally re-render deferred queries after calling refetch or setting skip to false to match the behavior of the initial fetch. Previously, the hook would not re-render until the entire result had finished loading in these cases.

    • #10399 652a1ae08 Thanks @alessbell! - Silence useLayoutEffect warning when useSuspenseQuery runs on server

    • #10919 f796ce1ac Thanks @jerelmiller! - Fix an issue when using a link that relied on operation.getContext and operation.setContext would error out when it was declared after the removeTypenameFromVariables link.

    • #10968 b102390b2 Thanks @phryneas! - Use printed query for query deduplication. Cache print calls for GraphQL documents to speed up repeated operations.

    • #11071 4473e925a Thanks @jerelmiller! - #10509 introduced some helpers for determining the type of operation for a GraphQL query. This imported the OperationTypeNode from graphql-js which is not available in GraphQL 14. To maintain compatibility with graphql-js v14, this has been reverted to use plain strings.

    • #10766 ffb179e55 Thanks @jerelmiller! - More robust typings for the data property returned from useSuspenseQuery when using returnPartialData: true or an errorPolicy of all or ignore. TData now defaults to unknown instead of any.

    • #10401 3e5b41a75 Thanks @jerelmiller! - Always throw network errors in useSuspenseQuery regardless of the set errorPolicy.

    • #10877 f40248598 Thanks @phryneas! - Change an import in useQuery and useMutation that added an unnecessary runtime dependency on @apollo/client/core. This drastically reduces the bundle size of each the hooks.

    • #10656 54c4d2f3c Thanks @jerelmiller! - Ensure refetch, fetchMore, and subscribeToMore functions returned by useSuspenseQuery are referentially stable between renders, even as data is updated.

    • #10324 95eb228be Thanks @jerelmiller! - Add @defer support to useSuspenseQuery.

    • #10888 1562a2f5a Thanks @alessbell! - Updates dependency versions in package.json by bumping:

      • @wry/context to ^0.7.3
      • @wry/equality to ^0.5.6
      • @wry/trie to ^0.4.3
      • optimism to ^0.17.4

      to 1. fix sourcemap warnings and 2. a Codesandbox sandpack (in-browser) bundler transpilation bug with an upstream optimism workaround.

    • #11010 1051a9c88 Thanks @alessbell! - Hide queryRef in a Symbol in useBackgroundQuerys return value.

    • #10758 9def7421f Thanks @phryneas! - use React.use where available

    • #11032 6a4da900a Thanks @jerelmiller! - Throw errors in useSuspenseQuery for errors returned in incremental chunks when errorPolicy is none. This provides a more consistent behavior of the errorPolicy in the hook.

      Potentially breaking change

      Previously, if you issued a query with @defer and relied on errorPolicy: 'none' to set the error property returned from useSuspenseQuery when the error was returned in an incremental chunk, this error is now thrown. Switch the errorPolicy to all to avoid throwing the error and instead return it in the error property.

    • #10960 ee407ef97 Thanks @alessbell! - Adds support for returnPartialData and refetchWritePolicy options in useBackgroundQuery hook.

    • #10809 49d28f764 Thanks @jerelmiller! - Fixed the ability to use refetch and fetchMore with React's startTransition. The hook will now behave correctly by allowing React to avoid showing the Suspense fallback when these functions are wrapped by startTransition. This change deprecates the suspensePolicy option in favor of startTransition.

    • #11082 0f1cde3a2 Thanks @phryneas! - Restore Apollo Client 3.7 getApolloContext behaviour

    • #10969 525a9317a Thanks @phryneas! - Slightly decrease bundle size and memory footprint of SuspenseCache by changing how cache entries are stored internally.

    • #11025 6092b6edf Thanks @jerelmiller! - useSuspenseQuery and useBackgroundQuery will now properly apply changes to its options between renders.

    • #10872 96b4f8837 Thanks @phryneas! - The "per-React-Version-Singleton" ApolloContext is now stored on globalThis, not React.createContext, and throws an error message when accessed from React Server Components.

    • #10450 f8bc33387 Thanks @jerelmiller! - Add support for the subscribeToMore and client fields returned in the useSuspenseQuery result.

    </details>

    Open source →
  27. 3.8.0-rc.21 Aug 2023pre-release
    Release notes

    3.8.0-rc.2

    Minor Changes

    • #11112 b4aefcfe9 Thanks @jerelmiller! - Adds support for a skipToken sentinel that can be used as options in useSuspenseQuery and useBackgroundQuery to skip execution of a query. This works identically to the skip option but is more type-safe and as such, becomes the recommended way to skip query execution. As such, the skip option has been deprecated in favor of skipToken.

      We are considering the removal of the skip option from useSuspenseQuery and useBackgroundQuery in the next major. We are releasing with it now to make migration from useQuery easier and make skipToken more discoverable.

      import { skipToken } from "@apollo/client";
      
      const id: number | undefined;
      
      const { data } = useSuspenseQuery(
        query,
        id ? { variables: { id } } : skipToken
      );
      

      Breaking change

      Previously useBackgroundQuery would always return a queryRef whenever query execution was skipped. This behavior been updated to return a queryRef only when query execution is enabled. If initializing the hook with it skipped, queryRef is now returned as undefined.

      To migrate, conditionally render the component that accepts the queryRef as props.

      Before

      function Parent() {
        const [queryRef] = useBackgroundQuery(query, skip ? skipToken : undefined);
        //      ^? QueryReference<TData | undefined>
      
        return <Child queryRef={queryRef} />;
      }
      
      function Child({
        queryRef,
      }: {
        queryRef: QueryReference<TData | undefined>;
      }) {
        const { data } = useReadQuery(queryRef);
      }
      

      After

      function Parent() {
        const [queryRef] = useBackgroundQuery(query, skip ? skipToken : undefined);
        //      ^? QueryReference<TData> | undefined
      
        return queryRef ? <Child queryRef={queryRef} /> : null;
      }
      
      function Child({ queryRef }: { queryRef: QueryReference<TData> }) {
        const { data } = useReadQuery(queryRef);
      }
      

    Patch Changes

    • #11086 0264fee06 Thanks @jerelmiller! - Fix an issue where a call to refetch, fetchMore, or changing skip to false that returned a result deeply equal to data in the cache would get stuck in a pending state and never resolve.

    • #11115 78739e3ef Thanks @phryneas! - Enforce export type for all type-level exports.

    • #11103 e3d611daf Thanks @caylahamann! - Fixes a bug in useMutation so that onError is called when an error is returned from the request with errorPolicy set to 'all' .

    • #11083 f766e8305 Thanks @phryneas! - Adjust the rerender timing of useQuery to more closely align with useFragment. This means that cache updates delivered to both hooks should trigger renders at relatively the same time. Previously, the useFragment might rerender much faster leading to some confusion.

    • #11082 0f1cde3a2 Thanks @phryneas! - Restore Apollo Client 3.7 getApolloContext behaviour

    Open source →
  28. 3.8.0-rc.117 Jul 2023pre-release
    Release notes

    3.8.0-rc.1

    Patch Changes

    • #11071 4473e925a Thanks @jerelmiller! - #10509 introduced some helpers for determining the type of operation for a GraphQL query. This imported the OperationTypeNode from graphql-js which is not available in GraphQL 14. To maintain compatibility with graphql-js v14, this has been reverted to use plain strings.
    Open source →
  29. 3.8.0-rc.013 Jul 2023pre-release
    Release notes

    3.8.0-rc.0

    Minor Changes

    • #11058 89bf33c42 Thanks @phryneas! - (Batch)HttpLink: Propagate AbortErrors to the user when a user-provided signal is passed to the link. Previously, these links would swallow all AbortErrors, potentially causing queries and mutations to never resolve. As a result of this change, users are now expected to handle AbortErrors when passing in a user-provided signal.

    • #11040 125ef5b2a Thanks @phryneas! - HttpLink/BatchHttpLink: Abort the AbortController signal more granularly. Before this change, when HttpLink/BatchHttpLink created an AbortController internally, the signal would always be .aborted after the request was completed. This could cause issues with Sentry Session Replay and Next.js App Router Cache invalidations, which just replayed the fetch with the same options - including the cancelled AbortSignal.

      With this change, the AbortController will only be .abort()ed by outside events, not as a consequence of the request completing.

    Patch Changes

    • #11053 c0ca70720 Thanks @phryneas! - Add SuspenseCache as a lazy hidden property on ApolloClient. This means that SuspenseCache is now an implementation details of Apollo Client and you no longer need to manually instantiate it and no longer need to pass it into ApolloProvider. Trying to instantiate a SuspenseCache instance in your code will now throw an error.

      Migration:

      -import { SuspenseCache } from '@apollo/client';
      
      -const suspenseCache = new SuspenseCache();
      
      -<ApolloProvider client={client} suspenseCache={suspenseCache} />;
      +<ApolloProvider client={client} />;
      
    Open source →
  30. 3.8.0-beta.710 Jul 2023pre-release
    Release notes

    3.8.0-beta.7

    Minor Changes

    • #10994 2ebbd3abb Thanks @phryneas! - Add .js file extensions to imports in src and dist/*/.d.ts

    • #11045 9c1d4a104 Thanks @jerelmiller! - When changing variables back to a previously used set of variables, do not automatically cache the result as part of the query reference. Instead, dispose of the query reference so that the InMemoryCache can determine the cached behavior. This means that fetch policies that would guarantee a network request are now honored when switching back to previously used variables.

    • #10915 3a62d8228 Thanks @phryneas! - Changes how development-only code is bundled in the library to more reliably enable consuming bundlers to reduce production bundle sizes while keeping compatibility with non-node environments.

    Patch Changes

    • #11026 b8d405eee Thanks @phryneas! - Store React.Context instance mapped by React.createContext instance, not React.version. Using React.version can cause problems with preact, as multiple versions of preact will all identify themselves as React 17.0.2.

    • #11000 1d43ab616 Thanks @phryneas! - Use import * as React everywhere. This prevents an error when importing @apollo/client in a React Server component. (see #10974)

    • #11035 a3ab7456d Thanks @jerelmiller! - Incrementally re-render deferred queries after calling refetch or setting skip to false to match the behavior of the initial fetch. Previously, the hook would not re-render until the entire result had finished loading in these cases.

    Open source →
  31. 3.8.0-beta.65 Jul 2023pre-release
    Release notes

    3.8.0-beta.6

    Patch Changes

    • #11027 e47cfd04e Thanks @phryneas! - Prevents the DevTool installation warning to be turned into a documentation link.

    • #11013 5ed2cfdaf Thanks @alessbell! - Make private fields inFlightLinkObservables and fetchCancelFns protected in QueryManager in order to make types available in @apollo/experimental-nextjs-app-support package when extending the ApolloClient class.

    • #11032 6a4da900a Thanks @jerelmiller! - Throw errors in useSuspenseQuery for errors returned in incremental chunks when errorPolicy is none. This provides a more consistent behavior of the errorPolicy in the hook.

      Potentially breaking change

      Previously, if you issued a query with @defer and relied on errorPolicy: 'none' to set the error property returned from useSuspenseQuery when the error was returned in an incremental chunk, this error is now thrown. Switch the errorPolicy to all to avoid throwing the error and instead return it in the error property.

    • #11025 6092b6edf Thanks @jerelmiller! - useSuspenseQuery and useBackgroundQuery will now properly apply changes to its options between renders.

    Open source →
  32. 3.8.0-beta.528 Jun 2023pre-release
    Release notes

    3.8.0-beta.5

    Patch Changes

    • #10999 c1904a78a Thanks @phryneas! - Fix a bug in QueryReference where this.resolve or this.reject might be executed even if undefined.

    • #11018 5618953f3 Thanks @jerelmiller! - useBackgroundQuery now uses its own options type called BackgroundQueryHookOptions rather than reusing SuspenseQueryHookOptions.

    • #11010 1051a9c88 Thanks @alessbell! - Hide queryRef in a Symbol in useBackgroundQuerys return value.

    • #10960 ee407ef97 Thanks @alessbell! - Adds support for returnPartialData and refetchWritePolicy options in useBackgroundQuery hook.

    Open source →
  33. 3.8.0-beta.420 Jun 2023pre-release
    Release notes

    3.8.0-beta.4

    Patch Changes

    • #10940 1d38f128f Thanks @jerelmiller! - Add support for the skip option in useBackgroundQuery and useSuspenseQuery. Setting this option to true will avoid a network request.
    Open source →
  34. 3.8.0-beta.315 Jun 2023pre-release
    Release notes

    3.8.0-beta.3

    Minor Changes

    • #10895 e187866fd Thanks @(author)! - Add generic type parameter for the entity modified in cache.modify. Improves TypeScript type inference for that type's fields and values of those fields.

      Example:

      cache.modify<Book>({
        id: cache.identify(someBook),
        fields: {
          title: (title) => {
            // title has type `string`.
            // It used to be `any`.
          },
       => {
            // author has type `Reference | Book["author"]`.
            // It used to be `any`.
          },
        },
      });
      
    • #10895 e187866fd Thanks @Gelio! - Use unique opaque types for the DELETE and INVALIDATE Apollo cache modifiers.

      This increases type safety, since these 2 modifiers no longer have the any type. Moreover, it no longer triggers the @typescript-eslint/no-unsafe-return rule.

    Patch Changes

    • #10951 2e833b2ca Thanks @alessbell! - Improve useBackgroundQuery type interface

    • #10964 f33171506 Thanks @alessbell! - Fixes a bug in BatchHttpLink that removed variables from all requests by default.

    • #10968 b102390b2 Thanks @phryneas! - Use printed query for query deduplication. Cache print calls for GraphQL documents to speed up repeated operations.

    • #10969 525a9317a Thanks @phryneas! - Slightly decrease bundle size and memory footprint of SuspenseCache by changing how cache entries are stored internally.

    Open source →
  35. 3.8.0-beta.27 Jun 2023pre-release
    Release notes

    3.8.0-beta.2

    Patch Changes

    Open source →
  36. 3.8.0-beta.131 May 2023pre-release
    Release notes

    3.8.0-beta.1

    Patch Changes

    • #10937 eea44eb87 Thanks @jerelmiller! - Moves DocumentTransform to the utilities sub-package to avoid a circular dependency between the core and cache sub-packages.

    • #10919 f796ce1ac Thanks @jerelmiller! - Fix an issue when using a link that relied on operation.getContext and operation.setContext would error out when it was declared after the removeTypenameFromVariables link.

    Open source →
  37. 3.8.0-beta.026 May 2023pre-release
    Release notes

    3.8.0-beta.0

    Minor Changes

    • #10887 f8c0b965d Thanks @phryneas! - Add a new mechanism for Error Extraction to reduce bundle size by including error message texts on an opt-in basis. By default, errors will link to an error page with the entire error message. This replaces "development" and "production" errors and works without additional bundler configuration. Bundling the text of error messages and development warnings can be enabled by

      import { loadErrorMessages, loadDevMessages } from "@apollo/client/dev";
      if (process.env.NODE_ENV !== "production") {
        loadErrorMessages();
        loadDevMessages();
      }
      
    • #10509 79df2c7ba Thanks @jerelmiller! - Add the ability to specify custom GraphQL document transforms. These transforms are run before reading data from the cache, before local state is resolved, and before the query document is sent through the link chain.

      To register a custom document transform, create a transform using the DocumentTransform class and pass it to the documentTransform option on ApolloClient.

      import { DocumentTransform } from "@apollo/client";
      
      const documentTransform = new DocumentTransform((document) => {
        // do something with `document`
        return transformedDocument;
      });
      
      const client = new ApolloClient({ documentTransform: documentTransform });
      

      For additional documentation on the behavior and API of DocumentTransform, see the pull request.

    • #10916 ea75e18de Thanks @alessbell! - Remove experimental labels from hooks, move to beta.

    Open source →
  38. 3.8.0-alpha.1517 May 2023pre-release
    Release notes

    3.8.0-alpha.15

    Patch Changes

    Open source →
  39. 3.8.0-alpha.1416 May 2023pre-release
    Release notes

    3.8.0-alpha.14

    Minor Changes

    • #10755 e3c676deb Thanks @alessbell! - Feature: adds useBackgroundQuery and useReadQuery hooks

    • #10853 300957960 Thanks @jerelmiller! - Introduce the new removeTypenameFromVariables link. This link will automatically remove __typename fields from variables for all operations. This link can be configured to exclude JSON-scalars for scalars that utilize __typename.

      This change undoes some work from #10724 where __typename was automatically stripped for all operations with no configuration. This was determined to be a breaking change and therefore moved into this link.

    Patch Changes

    • #10869 ba1d06166 Thanks @phryneas! - Ensure Context value stability when rerendering ApolloProvider with the same client and/or suspenseCache prop

    • #10789 23a4e1578 Thanks @phryneas! - Fix a bug where other fields could be aliased to __typename or id, in which case an incoming result would be merged into the wrong cache entry.

    • #10765 35f36c5aa Thanks @phryneas! - More robust types for the data property on UseFragmentResult. When a partial result is given, the type is now correctly set to Partial<TData>.

    • #10852 27fbdb3f9 Thanks @phryneas! - Chore: Add ESLint rule for consistent type imports, apply autofix

    • #10877 f40248598 Thanks @phryneas! - Change an import in useQuery and useMutation that added an unnecessary runtime dependency on @apollo/client/core. This drastically reduces the bundle size of each the hooks.

    • #10836 6794893c2 Thanks @phryneas! - Remove the deprecated returnPartialData option from useFragment hook.

    • #10872 96b4f8837 Thanks @phryneas! - The "per-React-Version-Singleton" ApolloContext is now stored on globalThis, not React.createContext, and throws an error message when accessed from React Server Components.

    Open source →
  40. 3.8.0-alpha.133 May 2023pre-release
    Release notes

    3.8.0-alpha.13

    Patch Changes

    • #10766 ffb179e55 Thanks @jerelmiller! - More robust typings for the data property returned from useSuspenseQuery when using returnPartialData: true or an errorPolicy of all or ignore. TData now defaults to unknown instead of any.

    • #10809 49d28f764 Thanks @jerelmiller! - Fixed the ability to use refetch and fetchMore with React's startTransition. The hook will now behave correctly by allowing React to avoid showing the Suspense fallback when these functions are wrapped by startTransition. This change deprecates the suspensePolicy option in favor of startTransition.

    Open source →
  41. 3.8.0-alpha.1213 Apr 2023pre-release
    Release notes

    3.8.0-alpha.12

    Minor Changes

    • #10722 c7e60f83d Thanks @benjamn! - Implement a @nonreactive directive for selectively skipping reactive comparisons of query result subtrees

    Patch Changes

    Open source →
  42. 3.8.0-alpha.1128 Mar 2023pre-release
    Release notes

    3.8.0-alpha.11

    Minor Changes

    • #10567 c2ce6496c Thanks @benjamn! - Allow ApolloCache implementations to specify default value for assumeImmutableResults client option, improving performance for applications currently using InMemoryCache without configuring new ApolloClient({ assumeImmutableResults: true })

    Patch Changes

    • #10672 932252b0c Thanks @jerelmiller! - Fix the compatibility between useSuspenseQuery and React's useDeferredValue and startTransition APIs to allow React to show stale UI while the changes to the variable cause the component to suspend.

      Breaking change

      nextFetchPolicy support has been removed from useSuspenseQuery. If you are using this option, remove it, otherwise it will be ignored.

    Open source →
  43. 3.8.0-alpha.1017 Mar 2023pre-release
    Release notes

    3.8.0-alpha.10

    Patch Changes

    • #10657 db305a800 Thanks @jerelmiller! - Return networkStatus in the useSuspenseQuery result.

    • #10651 8355d0e1e Thanks @jerelmiller! - Fixes an issue where useSuspenseQuery would not respond to cache updates when using a cache-first fetchPolicy after the hook was mounted with data already in the cache.

    • #10656 54c4d2f3c Thanks @jerelmiller! - Ensure refetch, fetchMore, and subscribeToMore functions returned by useSuspenseQuery are referentially stable between renders, even as data is updated.

    Open source →
  44. 3.8.0-alpha.915 Mar 2023pre-release
    Release notes

    3.8.0-alpha.9

    Patch Changes

    Open source →
  45. 3.8.0-alpha.82 Mar 2023pre-release
    Release notes

    3.8.0-alpha.8

    Patch Changes

    Open source →
  46. 3.8.0-alpha.715 Feb 2023pre-release
    Release notes

    3.8.0-alpha.7

    Minor Changes

    • #10527 0cc7e2e19 Thanks @phryneas! - Remove the query/mutation/subscription option from hooks that already take that value as their first argument.

    • #10506 2dc2e1d4f Thanks @phryneas! - prevent accidental widening of inferred TData and TVariables generics for query hook option arguments

    Open source →
  47. 3.8.0-alpha.67 Feb 2023pre-release
    Release notes

    3.8.0-alpha.6

    Minor Changes

    Patch Changes

    Open source →
  48. 3.8.0-alpha.519 Jan 2023pre-release
    Release notes

    3.8.0-alpha.5

    Patch Changes

    • #10450 f8bc33387 Thanks @jerelmiller! - Add support for the subscribeToMore and client fields returned in the useSuspenseQuery result.
    Open source →
  49. 3.8.0-alpha.413 Jan 2023pre-release
    Release notes

    3.8.0-alpha.4

    Patch Changes

    Open source →
  50. 3.8.0-alpha.33 Jan 2023pre-release
    Release notes

    3.8.0-alpha.3

    Patch Changes

    Open source →
  51. 3.8.0-alpha.221 Dec 2022pre-release
    Release notes

    3.8.0-alpha.2

    Minor Changes

    Open source →
  52. 3.8.0-alpha.121 Dec 2022pre-release
    Release notes

    3.8.0-alpha.15

    Patch Changes

    3.8.0-alpha.14

    3.8.0-alpha.13

    Patch Changes

    • #10766 ffb179e55 Thanks @jerelmiller! - More robust typings for the data property returned from useSuspenseQuery when using returnPartialData: true or an errorPolicy of all or ignore. TData now defaults to unknown instead of any.

    • #10809 49d28f764 Thanks @jerelmiller! - Fixed the ability to use refetch and fetchMore with React's startTransition. The hook will now behave correctly by allowing React to avoid showing the Suspense fallback when these functions are wrapped by startTransition. This change deprecates the suspensePolicy option in favor of startTransition.

    3.8.0-alpha.12

    3.8.0-alpha.11

    Minor Changes

    • #10567 c2ce6496c Thanks @benjamn! - Allow ApolloCache implementations to specify default value for assumeImmutableResults client option, improving performance for applications currently using InMemoryCache without configuring new ApolloClient({ assumeImmutableResults: true })

    Patch Changes

    • #10672 932252b0c Thanks @jerelmiller! - Fix the compatibility between useSuspenseQuery and React's useDeferredValue and startTransition APIs to allow React to show stale UI while the changes to the variable cause the component to suspend.

      Breaking change

      nextFetchPolicy support has been removed from useSuspenseQuery. If you are using this option, remove it, otherwise it will be ignored.

    3.8.0-alpha.10

    3.8.0-alpha.1

    Patch Changes

    Open source →
  53. 3.8.0-alpha.09 Dec 2022pre-release
    Release notes

    3.8.0-alpha.0

    Minor Changes

    Patch Changes

    Open source →
  54. 3.7.175 Jul 2023
    Release notes3 sources agree

    Patch Changes

    • #10631 b93388d75 Thanks @phryneas! - ObservableQuery.getCurrentResult: skip the cache if the running query should not access the cache
    Open source →
  55. 3.7.1620 Jun 2023
    Release notes

    Patch Changes

    • #10806 cb1540504 Thanks @phryneas! - Fix a bug in PersistedQueryLink that would cause it to permanently skip persisted queries after a 400 or 500 status code.

    • #10807 b32369592 Thanks @phryneas! - PersistedQueryLink will now also check for error codes in extensions.

    • #10982 b9be7a814 Thanks @sdeleur-sc! - Update relayStylePagination to avoid populating startCursor when only a single cursor is present under the edges field. Use that cursor only as the endCursor.

    • #10962 772cfa3cb Thanks @jerelmiller! - Remove useGETForQueries option in BatchHttpLink.Options type since it is not supported.

    Potentially breaking change in PersistedQueryLink

    Previously, if the PersistedQueryLink encountered a single 400 or 500 error, it would stop sending any persisted queries in the future. This allowed you to use the link even if a server had no support for persisted queries.

    We have decided to change this behavior, so now the PersistedQueryLink will only stop trying to send query hashes if the server responds with a PERSISTED_QUERY_NOT_SUPPORTED error code as it was unclear whether a 400 or 500 status code was in fact because the server did not support persisted queries.

    If you relied on the previous behaviour, maybe because you were communicating with a server that might or might not support persisted queries, but would return with a different kind of error, you can use the disable option callback to override this behavior like this:

    createPersistedQueryLink({
      // ... other options ...
      disable({ operation }){
        const { response } = operation.getContext();
        return (
          response &&
          response.status &&
          (response.status === 400 || response.status === 500)
        );
      }
    })
    

    Alternatively, consider removing the link entirely when your server does not support persisted queries.

    New Contributors

    • @sdeleur-sc made their first contribution in https://github.com/apollographql/apollo-client/pull/10982
    Open source →
    Additional notes2 sources agree

    Patch Changes

    • #10806 cb1540504 Thanks @phryneas! - Fix a bug in PersistedQueryLink that would cause it to permanently skip persisted queries after a 400 or 500 status code.

    • #10807 b32369592 Thanks @phryneas! - PersistedQueryLink will now also check for error codes in extensions.

    • #10982 b9be7a814 Thanks @sdeleur-sc! - Update relayStylePagination to avoid populating startCursor when only a single cursor is present under the edges field. Use that cursor only as the endCursor.

    • #10962 772cfa3cb Thanks @jerelmiller! - Remove useGETForQueries option in BatchHttpLink.Options type since it is not supported.

    Open source →
  56. 3.7.1526 May 2023
    Release notes

    Patch Changes

    • #10891 ab42a5c08 Thanks @laverdet! - Fixes a bug in how multipart responses are read when using @defer. When reading a multipart body, HttpLink no longer attempts to parse the boundary (e.g. "---" or other boundary string) within the response data itself, only when reading the beginning of each mulitpart chunked message.

    • #10789 23a4e1578 Thanks @phryneas! - Fix a bug where other fields could be aliased to __typename or id, in which case an incoming result would be merged into the wrong cache entry.

    New Contributors

    • @AngadSethi made their first contribution in https://github.com/apollographql/apollo-client/pull/10837
    • @laverdet made their first contribution in https://github.com/apollographql/apollo-client/pull/10891
    • @beerose made their first contribution in https://github.com/apollographql/apollo-client/pull/10910
    Open source →
    Additional notes2 sources agree

    Patch Changes

    • #10891 ab42a5c08 Thanks @laverdet! - Fixes a bug in how multipart responses are read when using @defer. When reading a multipart body, HttpLink no longer attempts to parse the boundary (e.g. "---" or other boundary string) within the response data itself, only when reading the beginning of each mulitpart chunked message.

    • #10789 23a4e1578 Thanks @phryneas! - Fix a bug where other fields could be aliased to __typename or id, in which case an incoming result would be merged into the wrong cache entry.

    Open source →
  57. 3.7.143 May 2023
    Release notes

    Patch Changes

    • #10764 1b0a61fe5 Thanks @phryneas! - Deprecate useFragment returnPartialData option

    • #10810 a6252774f Thanks @dleavitt! - Fix type signature of ServerError.

      In <3.7 HttpLink and BatchHttpLink would return a ServerError.message of e.g. "Unexpected token 'E', \"Error! Foo bar\" is not valid JSON" and a ServerError.result of undefined in the case where a server returned a >= 300 response code with a response body containing a string that could not be parsed as JSON.

      In >=3.7, message became e.g. Response not successful: Received status code 302 and result became the string from the response body, however the type in ServerError.result was not updated to include the string type, which is now properly reflected.

    Open source →
    Additional notes2 sources agree

    Patch Changes

    • #10764 1b0a61fe5 Thanks @phryneas! - Deprecate useFragment returnPartialData option

    • #10810 a6252774f Thanks @dleavitt! - Fix type signature of ServerError.

      In <3.7 HttpLink and BatchHttpLink would return a ServerError.message of e.g. "Unexpected token 'E', \"Error! Foo bar\" is not valid JSON" and a ServerError.result of undefined in the case where a server returned a >= 300 response code with a response body containing a string that could not be parsed as JSON.

      In >=3.7, message became e.g. Response not successful: Received status code 302 and result became the string from the response body, however the type in ServerError.result was not updated to include the string type, which is now properly reflected.

    Open source →
  58. 3.7.1327 Apr 2023
    Release notes3 sources agree

    Patch Changes

    • #10805 a5503666c Thanks @phryneas! - Fix a potential memory leak in SSR scenarios when many persistedQuery instances were created over time.

    • #10718 577c68bdd Thanks @Hsifnus! - Delay Concast subscription teardown slightly in useSubscription to prevent unexpected Concast teardown when one useSubscription hook tears down its in-flight Concast subscription immediately followed by another useSubscription hook reusing and subscribing to that same Concast

    Open source →
  59. 3.7.1212 Apr 2023
    Release notes3 sources agree

    Patch Changes

    • #10735 895bcdcff Thanks @alessbell! - If a multipart chunk contains only hasNext: false, immediately complete the observable.
    Open source →
  60. 3.7.1131 Mar 2023
    Release notes

    Patch Changes

    • #10586 4175af594 Thanks @alessbell! - Improve WebSocket error handling for generic Event received on error. For more information see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event.

    • #10411 152baac34 Thanks @lovasoa! - Simplify error message generation and make 'undefined' an impossible message string.

    • #10592 cdb98ae08 Thanks @alessbell! - Adds support for multipart subscriptions in HttpLink.

    • #10698 38508a251 Thanks @jerelmiller! - Changes the behavior of useLazyQuery introduced in #10427 where unmounting a component before a query was resolved would reject the promise with an abort error. Instead, the promise will now resolve naturally with the result from the request.

      Other notable fixes:

      • Kicking off multiple requests in parallel with the execution function will now ensure each returned promise is resolved with the data from its request. Previously, each promise was resolved with data from the last execution.
      • Re-rendering useLazyQuery with a different query document will now ensure the execution function uses the updated query document. Previously, only the query document rendered the first time would be used for the request.
    • #10660 364bee98f Thanks @alessbell! - Upgrades TypeScript to v5. This change is fully backward-compatible and transparent to users.

    • #10597 8fb9d190d Thanks @phryneas! - Fix a bug where an incoming cache update could prevent future updates from the active link.

    • #10629 02605bb3c Thanks @phryneas! - useQuery: delay unsubscribe to fix race conditions

    Open source →
    Additional notes2 sources agree

    Patch Changes

    • #10586 4175af594 Thanks @alessbell! - Improve WebSocket error handling for generic Event received on error. For more information see https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/error_event.

    • #10411 152baac34 Thanks @lovasoa! - Simplify error message generation and make 'undefined' an impossible message string.

    • #10592 cdb98ae08 Thanks @alessbell! - Adds support for multipart subscriptions in HttpLink.

    • #10698 38508a251 Thanks @jerelmiller! - Changes the behavior of useLazyQuery introduced in #10427 where unmounting a component before a query was resolved would reject the promise with an abort error. Instead, the promise will now resolve naturally with the result from the request.

      Other notable fixes:

      • Kicking off multiple requests in parallel with the execution function will now ensure each returned promise is resolved with the data from its request. Previously, each promise was resolved with data from the last execution.
      • Re-rendering useLazyQuery with a different query document will now ensure the execution function uses the updated query document. Previously, only the query document rendered the first time would be used for the request.
    • #10660 364bee98f Thanks @alessbell! - Upgrades TypeScript to v5. This change is fully backward-compatible and transparent to users.

    • #10597 8fb9d190d Thanks @phryneas! - Fix a bug where an incoming cache update could prevent future updates from the active link.

    • #10629 02605bb3c Thanks @phryneas! - useQuery: delay unsubscribe to fix race conditions

    Open source →