:rocket: A fully-featured, production ready caching GraphQL client for every UI framework and GraphQL server.
7623da7
Thanks @alessbell! - Add watchFragment
method to the cache and expose it on ApolloClient, refactor useFragment
using watchFragment
.#11595 8c20955
Thanks @phryneas! - Bumps the dependency rehackt
to 0.0.5
#11592 1133469
Thanks @Stephen2! - Strengthen MockedResponse.newData
type
#11579 1ba2fd9
Thanks @jerelmiller! - Fix issue where partial data is reported to useQuery
when using notifyOnNetworkStatusChange
after it errors while another overlapping query succeeds.
#11579 1ba2fd9
Thanks @jerelmiller! - Fix an issue where a partial cache write for an errored query would result in automatically refetching that query.
#11562 65ab695
Thanks @mspiess! - Mocks with an infinite delay no longer require result or error
#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
#11525 dce923a
Thanks @vezaynk! - Allows passing in client via options to useFragment
#11558 8cba16f
Thanks @alessbell! - Fix unbound-method
linter error on ObservableQuery methods exposed on useQuery's QueryResult object.
6ac2b0c
Thanks @jerelmiller! - Fix import in useLazyRef
causing import issues in the nextjs package.#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.
#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
WeakCache
instead of Map
to keep a limited number of parsed resultsparse.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
WeakCache
instead of WeakMap
to keep a limited number of hash resultspersistedLink.resetHashCache()
method#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
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);
// ...
}
createQueryPreloader
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.#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.
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);
// ...
}
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
}
#11301 46ab032
Thanks @alessbell! - Add multipart subscription network adapters for Relay and urql
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()),
});
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!
@apollo/experimental-nextjs-app-support
updateIf 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.
#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
.
#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
.