3.4.0
Apollo Client 3.4.0
New documentation
- Refetching queries with
client.refetchQueries
.
@StephenBarlow and @benjamn in #8265
Improvements
-
InMemoryCache
now guarantees that any two result objects returned by the cache (fromreadQuery
,readFragment
, etc.) will be referentially equal (===
) if they are deeply equal. Previously,===
equality was often achievable for results for the same query, on a best-effort basis. Now, equivalent result objects will be automatically shared among the result trees of completely different queries. This guarantee is important for taking full advantage of optimistic updates that correctly guess the final data, and for "pure" UI components that can skip re-rendering when their input data are unchanged.
@benjamn in #7439 -
Mutations now accept an optional callback function called
onQueryUpdated
, which will be passed theObservableQuery
andCache.DiffResult
objects for any queries invalidated by cache writes performed by the mutation's finalupdate
function. UsingonQueryUpdated
, you can override the defaultFetchPolicy
of the query, by (for example) callingObservableQuery
methods likerefetch
to force a network request. This automatic detection of invalidated queries provides an alternative to manually enumerating queries using therefetchQueries
mutation option. Also, if you return aPromise
fromonQueryUpdated
, the mutation will automatically await thatPromise
, rendering theawaitRefetchQueries
option unnecessary.
@benjamn in #7827 -
Support
client.refetchQueries
as an imperative way to refetch queries, without having to passoptions.refetchQueries
toclient.mutate
.
@dannycochran in #7431 -
Improve standalone
client.refetchQueries
method to support automatic detection of queries needing to be refetched.
@benjamn in #8000 -
Fix remaining barriers to loading
@apollo/client/core
as native ECMAScript modules from a CDN like esm.run. Importing@apollo/client
from a CDN will become possible once we move all React-related dependencies into@apollo/client/react
in Apollo Client 4.
@benjamn in #8266 -
InMemoryCache
supports a new method calledbatch
, which is similar toperformTransaction
but takes named options rather than positional parameters. One of these named options is anonDirty(watch, diff)
callback, which can be used to determine which watched queries were invalidated by thebatch
operation.
@benjamn in #7819 -
Allow
merge: true
field policy to mergeReference
objects with non-normalized objects, and vice-versa.
@benjamn in #7778 -
Allow identical subscriptions to be deduplicated by default, like queries.
@jkossis in #6910 -
Always use
POST
request when falling back to sending full query with@apollo/client/link/persisted-queries
.
@rieset in #7456 -
The
FetchMoreQueryOptions
type now takes two instead of three type parameters (<TVariables, TData>
), thanks to usingPartial<TVariables>
instead ofK extends typeof TVariables
andPick<TVariables, K>
.
@ArnaudBarre in #7476 -
Pass
variables
andcontext
to a mutation'supdate
function. Note: The type of theupdate
function is now namedMutationUpdaterFunction
rather thanMutationUpdaterFn
, since the older type was broken beyond repair. If you are usingMutationUpdaterFn
in your own code, please useMutationUpdaterFunction
instead.
@jcreighton in #7902 -
A
resultCacheMaxSize
option may be passed to theInMemoryCache
constructor to limit the number of result objects that will be retained in memory (to speed up repeated reads), and callingcache.reset()
now releases all such memory.
@SofianHn in #8701 -
Fully remove result cache entries from LRU dependency system when the corresponding entities are removed from
InMemoryCache
by eviction, or by any other means.
@sofianhn and @benjamn in #8147 -
Add expected/received
variables
toNo more mocked responses...
error messages generated byMockLink
.
@markneub in #8340 -
The
InMemoryCache
version of thecache.gc
method now supports additional options for removing non-essential (recomputable) result caching data.
@benjamn in #8421 -
Suppress noisy
Missing cache result fields...
warnings by default unlesssetLogVerbosity("debug")
called.
@benjamn in #8489 -
Improve interaction between React hooks and React Fast Refresh in development.
@andreialecu in #7952
Potentially disruptive changes
-
To avoid retaining sensitive information from mutation root field arguments, Apollo Client v3.4 automatically clears any
ROOT_MUTATION
fields from the cache after each mutation finishes. If you need this information to remain in the cache, you can prevent the removal by passing thekeepRootFields: true
option toclient.mutate
.ROOT_MUTATION
result data are also passed to the mutationupdate
function, so we recommend obtaining the results that way, rather than usingkeepRootFields: true
, if possible.
@benjamn in #8280 -
Internally, Apollo Client now controls the execution of development-only code using the
__DEV__
global variable, rather thanprocess.env.NODE_ENV
. While this change should not cause any visible differences in behavior, it will increase your minified+gzip bundle size by more than 3.5kB, unless you configure your minifier to replace__DEV__
with atrue
orfalse
constant, the same way you already replaceprocess.env.NODE_ENV
with a string literal like"development"
or"production"
. For an example of configuring a Create React App project without ejecting, see this pull request for our React Apollo reproduction template.
@benjamn in #8347 -
Internally, Apollo Client now uses namespace syntax (e.g.
import * as React from "react"
) for imports whose types are re-exported (and thus may appear in.d.ts
files). This change should remove any need to configureesModuleInterop
orallowSyntheticDefaultImports
intsconfig.json
, but might require updating bundler configurations that specify named exports of thereact
andprop-types
packages, to include exports likecreateContext
andcreateElement
(example).
@devrelm in #7742 -
Respect
no-cache
fetch policy (by not reading anydata
from the cache) forloading: true
results triggered bynotifyOnNetworkStatusChange: true
.
@jcreighton in #7761 -
The TypeScript return types of the
getLastResult
andgetLastError
methods ofObservableQuery
now correctly include the possibility of returningundefined
. If you happen to be calling either of these methods directly, you may need to adjust how the calling code handles the methods' possibly-undefined
results.
@benjamn in #8394 -
Log non-fatal
invariant.error
message when fields are missing from result objects written intoInMemoryCache
, rather than throwing an exception. While this change relaxes an exception to be merely an error message, which is usually a backwards-compatible change, the error messages are logged in more cases now than the exception was previously thrown, and those new error messages may be worth investigating to discover potential problems in your application. The errors are not displayed for@client
-only fields, so adding@client
is one way to handle/hide the errors for local-only fields. Another general strategy is to use a more precise query to write specific subsets of data into the cache, rather than reusing a larger query that contains fields not present in the writtendata
.
@benjamn in #8416 -
The
nextFetchPolicy
option forclient.watchQuery
anduseQuery
will no longer be removed from theoptions
object after it has been applied, and instead will continue to be applied any timeoptions.fetchPolicy
is reset to another value, until/unless theoptions.nextFetchPolicy
property is removed fromoptions
.
@benjamn in #8465 -
The
fetchMore
,subscribeToMore
, andupdateQuery
functions returned from theuseQuery
hook may now return undefined in edge cases where the functions are called when the component is unmounted.
@noghartt in #7980
Bug fixes
-
In Apollo Client 2.x, a
refetch
operation would always replace existing data in the cache. With the introduction of field policymerge
functions in Apollo Client 3, existing field values could be inappropriately combined with incoming field values by a custommerge
function that does not realize arefetch
has happened.To give you more control over this behavior, we have introduced an
overwrite?: boolean = false
option forcache.writeQuery
andcache.writeFragment
, and an option calledrefetchWritePolicy?: "merge" | "overwrite"
forclient.watchQuery
,useQuery
, and other functions that acceptWatchQueryOptions
. You can use these options to make sure anymerge
functions involved in cache writes forrefetch
operations get invoked withundefined
as their first argument, which simulates the absence of any existing data, while still giving themerge
function a chance to determine the internal representation of the incoming data.The default behaviors are
overwrite: true
andrefetchWritePolicy: "overwrite"
, which restores the Apollo Client 2.x behavior, but (if this change causes any problems for your application) you can easily recover the previous merging behavior by setting a default value forrefetchWritePolicy
indefaultOptions.watchQuery
:new ApolloClient({ defaultOptions: { watchQuery: { refetchWritePolicy: "merge", }, }, })
-
Make sure the
MockedResponse
ResultFunction
type is re-exported.
@hwillson in #8315 -
InMemoryCache
now coalescesEntityStore
updates to guarantee only onestore.merge(id, fields)
call perid
per cache write.
@benjamn in #8372 -
Fix polling when used with
<React.StrictMode>
.
@brainkim in #8414 -
Fix the React integration logging
Warning: Can't perform a React state update on an unmounted component
.
@wuarmin in #7745 -
Make
ObservableQuery#getCurrentResult
always callqueryInfo.getDiff()
.
@benjamn in #8422 -
Make
readField
default to reading from current object only when thefrom
option/argument is actually omitted, not whenfrom
is passed toreadField
with an undefined value. A warning will be printed when this situation occurs.
@benjamn in #8508 -
The
fetchMore
,subscribeToMore
, andupdateQuery
functions no longer throwundefined
errors.
@noghartt in #7980