Major Changes
-
#12614
d2851e2
Thanks @jerelmiller! - ThegetCacheKey
function is no longer available fromoperation.getContext()
in the link chain. Useoperation.client.cache.identify(obj)
in the link chain instead. -
#12556
c3fceda
Thanks @phryneas! -ObservableQuery
will now keep previousdata
around when emitting aloading
state, unlessquery
orvariables
changed.
Note that@exports
variables are not taken into account for this, sodata
will stay around even if they change. -
#12556
c3fceda
Thanks @phryneas! - RemovedgetLastResult
,getLastError
andresetLastResults
fromObservableQuery
-
#12614
d2851e2
Thanks @jerelmiller! - Removes theresolvers
option fromApolloClient
. Local resolvers have instead been moved to the newLocalState
instance which is assigned to thelocalState
option inApolloClient
. To migrate, move theresolvers
values into aLocalState
instance and assign that instance tolocalState
.new ApolloClient({ - resolvers: { /* ... */ } + localState: new LocalState({ + resolvers: { /* ... */ } + }), });
-
#12614
d2851e2
Thanks @jerelmiller! - Remove local resolvers APIs fromApolloClient
in favor oflocalState
. Methods removed are:addResolvers
getResolvers
setResolvers
setLocalStateFragmentMatcher
-
#12614
d2851e2
Thanks @jerelmiller! - Third-party caches must now implement thefragmentMatches
API. AdditionallyfragmentMatches
must be able to handle bothInlineFragmentNode
andFragmentDefinitionNode
nodes.class MyCache extends ApolloCache { // This is now required public fragmentMatches( fragment: InlineFragmentNode | FragmentDefinitionNode, typename: string ): boolean { return; // ... logic to determine if typename matches fragment } }
-
#12556
c3fceda
Thanks @phryneas! - Reworked the logic for then a loading state is triggered. If the link chain responds synchronously, a loading state will be omitted, otherwise it will be triggered.
If local resolvers are used, the time window for "sync vs async" starts as soon as@exports
variables are resolved. -
#12556
c3fceda
Thanks @phryneas! - Dropped thesaveAsLastResult
argument fromObservableQuery.getCurrentResult
-
#12614
d2851e2
Thanks @jerelmiller! - The resolver function'scontext
argument (the 3rd argument) has changed to provide additional information without the possibility of name clashes. Previously thecontext
argument would spread request context and override theclient
andcache
properties to give access to both inside of a resolver. Thecontext
argument takes now takes the following shape:{ // the request context. By default `TContextValue` is of type `DefaultContext`, // but can be changed if a `context` function is provided. requestContext: TContextValue, // The client instance making the request client: ApolloClient, // Whether the resolver is run as a result of gathering exported variables // or resolving the value as part of the result phase: "exports" | "resolve" }
To migrate, pull any request context from
requestContext
and thecache
from theclient
property:new LocalState({ resolvers: { Query: { - myResolver: (parent, args, { someValue, cache }) => { + myResolver: (parent, args, { requestContext, client }) => { + const someValue = requestContext.someValue; + const cache = client.cache; } } } });
-
#12614
d2851e2
Thanks @jerelmiller! - Apollo Client no longer ships with support for@client
fields out-of-the-box and now must be opt-in. To opt in to use@client
fields, pass an instantiatedLocalState
instance to thelocalState
option. If a query contains@client
and local state hasn't been configured, an error will be thrown.import { LocalState } from "@apollo/client/local-state"; new ApolloClient({ localState: new LocalState(), });
-
#12614
d2851e2
Thanks @jerelmiller! - Remove thefragmentMatcher
option fromApolloClient
. Custom fragment matchers used with local state are no longer supported. Fragment matching is now performed by the configuredcache
via thecache.fragmentMatches
API. -
#12556
c3fceda
Thanks @phryneas! - A call toObservableQuery.setVariables
with different variables or aObservableQuery.refetch
call will always now guarantee that a value will be emitted from the observable, even if it is deep equal to the previous value.
Minor Changes
-
#12614
d2851e2
Thanks @jerelmiller! - Revamp local resolvers and fix several issues from the existingresolvers
option.- Throwing errors in a resolver will set the field value as
null
and add an error to the response'serrors
array. - Remote results are dealiased before they are passed as the parent object to a resolver so that you can access fields by their field name.
- You can now specify a
context
function that you can use to customize therequestContext
given to resolvers. - The
LocalState
class accepts aResolvers
generic that provides autocompletion and type checking against your resolver types to ensure your resolvers are type-safe. data: null
is now handled correctly and does not call your local resolvers when the server does not provide a result.- Additional warnings have been added to provide hints when resolvers behave unexpectedly.
import { LocalState } from "@apollo/client/local-state"; import { Resolvers } from "./path/to/local-resolvers-types.ts"; // LocalState now accepts a `Resolvers` generic. const localState = new LocalState<Resolvers>({ // The return value of this funciton context: (options) => ({ // ... }), resolvers: { // ... }, }); // You may also pass a `ContextValue` generic used to ensure the `context` // function returns the correct type. This type is inferred from your resolvers // if not provided. new LocalState<Resolvers, ContextValue>({ // ... });
- Throwing errors in a resolver will set the field value as