Cerulean
Cerulean

Reputation: 6013

With Apollo React client, why you not always need a resolver to resolve @client GraphQL queries?

I'm learning how to use Apollo Client for React and how to manage local state using the cache. From the docs, it's as simple as writing to the cache using cache.writeData and reading from it using a simple query. Their example is

const GET_VISIBILITY_FILTER = gql`
  {
    visibilityFilter @client
  }
`;

I then wrap my JSX in a Query and can read the value fine (in my case loggedIn)

 return <Query query={GET_LOGGED_IN}>
      {({loading, error, data}) => {

        const {loggedIn} = data

I'm curious, though, why I don't need to write a resolver for this to work. Is it because with scalar values if a value exists at the root of an object, that is, here at the top level of the cache, Apollo/GraphQL automatically just grabs that value and sends it to you without a resolver?

What are the limits of this, that is, could you grab arrays at the root level without writing a resolver? Objects? I'm assuming not, as these don't seem to be scalars. But if the data is hard-coded, that is, doesn't require any DB lookup, the answer is still no?

Upvotes: 1

Views: 953

Answers (2)

xadm
xadm

Reputation: 8418

In addition to a great (as usual) answer from Daniel, I would like to add a few words.

You can use (read/write) objects to cache and manipulate its properties directly.

Using resolvers and mutations for local data can help with readability, data access/change unification, overal manageability or future changes (move feature/settings to server).

More practical/advanced example of local state managament you can find in apollo-universal-starter-kit project.

Upvotes: 1

Daniel Rearden
Daniel Rearden

Reputation: 84677

From the docs:

[The @client directive] tells Apollo Client to fetch the field data locally (either from the cache or using a local resolver), instead of sending it to our GraphQL server.

If the directive is present on a field, Apollo will attempt to resolve the field using the provided resolver, or fall back to fetching directly from the cache if one doesn't exist. You can initialize your cache with pretty much any sort of data at the root level (taking care to include __typename fields for objects) and you should be able to fetch it without having to also provide a resolver for it. On the other hand, providing a resolver can provide you with more granular control over what's actually fetched from the cache -- i.e. you could initialize the cache with an array of items, but use a resolver to provide a way to filter or sort them.

There's an import nuance here: Fetching without a resolver only works when there's data in the cache to fetch. That's why it's important to provide initial state for these fields when building your client. If you have a more deeply nested @client field (for example, maybe you're including additional information alongside data fetched from the server), you also technically don't have to write a resolver. But we typically do write them because there is no existing data in the cache for those nested fields.

Upvotes: 4

Related Questions