18
votes

I've been following the Apollo Client docs on local state.

I've implemented a very simple query of the client cache:

export const GET_USER_ACCOUNTS = gql`
    query GetUserAccounts {
        userAccounts @client
        name @client
    }
`;

userAccounts and name are both stored in my cache following authentication:

    <Mutation
          mutation={API_TOKEN_AUTHENTICATION}
          variables={{ apiKey }}
          onCompleted={({
              apiTokenAuthentication: {
                  token,
                  userAccounts,
                  user: { givenName, familyName },
               },
          }) => {
             localStorage.setItem('token', token);
             client.writeData({
                 data: {
                     isLoggedIn: true,
                     userAccounts,
                     name: `${givenName} ${familyName}`,
                 },
             });
         }}
    >

and I've warmed the cache with default values:

import { ApolloClient } from 'apollo-client';
import { InMemoryCache } from 'apollo-cache-inmemory';
import { HttpLink } from 'apollo-link-http';

const cache = new InMemoryCache();
const link = new HttpLink({
    uri: 'http://localhost:8002/v1/graphql',
    headers: {
        Authorization: `${localStorage.getItem('token')}`,
    },
});
const client = new ApolloClient({
    cache,
    link,
});
// set up the initial state
cache.writeData({
    data: {
        name: '',
        userAccounts: [],
        isLoggedIn: !!localStorage.getItem('token'),
    },
});

export default client;

I've not included any local resolvers, since the docs state:

When Apollo Client executes this query and tries to find a result for the isInCart field, it runs through the following steps:

Has a resolver function been set (either through the ApolloClient constructor resolvers parameter or Apollo Client's setResolvers / addResolvers methods) that is associated with the field name isInCart? If yes, run and return the result from the resolver function.

If a matching resolver function can't be found, check the Apollo Client cache to see if a isInCart value can be found directly. If so, return that value.

However, despite the code working fine (it fetches the values I want no problem) I still get this warning:

Found @client directives in query but no client resolvers were specified. You can now pass apollo-link-state resolvers to the ApolloClient constructor.

Have I misunderstood? Should I be including a client resolver for this in some way?

Any advice appreciated

2

2 Answers

33
votes

From the docs:

⚠️ If you want to use Apollo Client's @client support to query the cache without using local resolvers, you must pass an empty object into the ApolloClient constructor resolvers option. Without this Apollo Client will not enable its integrated @client support, which means your @client based queries will be passed to the Apollo Client link chain. You can find more details about why this is necessary here.

In other words, just add an empty resolvers object to your configuration like this:

const client = new ApolloClient({
    cache,
    link,
    resolvers: {},
});
6
votes

As Daniel later mentioned in the comments of the above answer, passing resolvers={{}} inside of MockedProvider worked wonderfully for me. Here's how it should look like:

<MockedProvider mocks={mocks} addTypename={false} resolvers={{}}>
    <FooComponent />
</MockedProvider>

It even solved a memory leakage problem I was having in Circle CI, as it seems there was nowhere to resolve to; here are the error messages I was getting:

<--- Last few GCs --->

  154665 ms: Mark-sweep 949.1 (1434.4) -> 948.2 (1434.4) MB, 1979.3 / 0 ms [allocation failure] [GC in old space requested].
  156664 ms: Mark-sweep 948.2 (1434.4) -> 948.2 (1434.4) MB, 1999.7 / 0 ms [allocation failure] [GC in old space requested].
  158734 ms: Mark-sweep 948.2 (1434.4) -> 948.2 (1434.4) MB, 2069.7 / 0 ms [last resort gc].
  160810 ms: Mark-sweep 948.2 (1434.4) -> 948.1 (1434.4) MB, 2075.7 / 0 ms [last resort gc].


<--- JS stacktrace --->

==== JS stack trace =========================================

Security context: 0x30ab306c9fa9 <JS Object>
    2: convertPropertyValueToJson(aka convertPropertyValueToJson) [/home/circleci/project/node_modules/typescript/lib/typescript.js:24737] [pc=0x2953c91d9878] (this=0x30ab30604189 <undefined>,valueExpression=0x39effa032fa9 <a NodeObject with map 0x35eb62463c11>,option=0x30ab30604189 <undefined>)
    3: /* anonymous */(aka /* anonymous */) [/home/circleci/project/node_modules/typescript/lib/type...

FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory
Aborted (core dumped)

Cheers!