Skip to content

Commit

Permalink
Merge pull request #7864 from apollographql/sb/cache-interaction-tweaks
Browse files Browse the repository at this point in the history
Edits to reading and writing cached data
  • Loading branch information
Stephen Barlow authored Mar 23, 2021
2 parents f5f1914 + 83ff39e commit 2484794
Show file tree
Hide file tree
Showing 6 changed files with 226 additions and 50 deletions.
6 changes: 3 additions & 3 deletions docs/source/api/cache/InMemoryCache.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ readQuery<QueryType, TVariables = any>(

Writes data to the cache in the shape of a provided GraphQL query. Returns a `Reference` to the written object or `undefined` if the write failed.

For usage instructions, see [Interacting with cached data: `writeQuery`](../../caching/cache-interaction/#writequery-and-writefragment).
For usage instructions, see [Interacting with cached data: `writeQuery`](../../caching/cache-interaction/#writequery).

Takes an `options` object as a parameter. Supported fields of this object are described below.

Expand Down Expand Up @@ -398,7 +398,7 @@ readFragment<FragmentType, TVariables = any>(

Writes data to the cache in the shape of the provided GraphQL fragment. Returns a `Reference` to the written object or `undefined` if the write failed.

For usage instructions, see [Interacting with cached data: `writeFragment`](../../caching/cache-interaction/#writequery-and-writefragment).
For usage instructions, see [Interacting with cached data: `writeFragment`](../../caching/cache-interaction/#writefragment).

Takes an `options` object as a parameter. Supported fields of this object are described below.

Expand Down Expand Up @@ -567,7 +567,7 @@ Modifies one or more field values of a cached object. Must provide a **modifier

Returns `true` if the cache was modified successfully and `false` otherwise.

For usage instructions, see [`cache.modify`](../../caching/cache-interaction/#cachemodify).
For usage instructions, see [Using `cache.modify`](../../caching/cache-interaction/#using-cachemodify).

Takes an `options` object as a parameter. Supported fields of this object are described below.

Expand Down
2 changes: 1 addition & 1 deletion docs/source/api/react/hoc.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -902,7 +902,7 @@ This option allows you to update your store based on your mutation’s result. B

`options.update` takes two arguments. The first is an instance of a `DataProxy` object which has some methods which will allow you to interact with the data in your store. The second is the response from your mutation - either the optimistic response, or the actual response returned by your server (see the mutation result described in the [mutation render prop](./components/#render-prop-function-1) section for more details).

In order to change the data in your store call methods on your `DataProxy` instance like [`writeQuery` and `writeFragment`](../../caching/cache-interaction/#writequery-and-writefragment). This will update your cache and reactively re-render any of your GraphQL components which are querying affected data.
In order to change the data in your store call methods on your `DataProxy` instance like [`writeQuery`](../../caching/cache-interaction/#writequery) and [`writeFragment`](../../caching/cache-interaction/#writefragment). This will update your cache and reactively re-render any of your GraphQL components which are querying affected data.

To read the data from the store that you are changing, make sure to use methods on your `DataProxy` like [`readQuery`](../../caching/cache-interaction/#readquery) and [`readFragment`](../../caching/cache-interaction/#readfragment).

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ title: Configuring the cache
sidebar_title: Configuration
---

import {ExpansionPanel} from 'gatsby-theme-apollo-docs';

Apollo Client stores the results of its GraphQL queries in a normalized, in-memory cache. This enables your client to respond to future queries for the same data without sending unnecessary network requests.

This article describes cache setup and configuration. To learn how to interact with cached data, see [Reading and writing data to the cache](./cache-interaction).
Expand Down Expand Up @@ -54,12 +56,14 @@ To customize cache behavior, provide an `options` object to the `InMemoryCache`
###### `addTypename`

`Boolean`

</td>
<td>

If `true`, the cache automatically adds `__typename` fields to all outgoing queries, removing the need to add them manually.

The default value is `true`.

</td>
</tr>

Expand All @@ -69,12 +73,14 @@ The default value is `true`.
###### `resultCaching`

`Boolean`

</td>
<td>

If `true`, the cache returns an identical (`===`) response object for every execution of the same query, as long as the underlying data remains unchanged. This makes it easier to detect changes to a query's result.

The default value is `true`.

</td>
</tr>

Expand All @@ -84,6 +90,7 @@ The default value is `true`.
###### `possibleTypes`

`Object`

</td>
<td>

Expand All @@ -92,6 +99,7 @@ Include this object to define polymorphic relationships between your schema's ty
Each key in the object is the `__typename` of an interface or union, and the corresponding value is an array of the `__typename`s of the types that belong to that union or implement that interface.

For an example, see [Defining `possibleTypes` manually](../data/fragments/#defining-possibletypes-manually).

</td>
</tr>

Expand All @@ -101,12 +109,14 @@ For an example, see [Defining `possibleTypes` manually](../data/fragments/#defin
###### `typePolicies`

`Object`

</td>
<td>

Include this object to customize the cache's behavior on a type-by-type basis.

Each key in the object is the `__typename` of a type to customize, and the corresponding value is a [`TypePolicy` object](#typepolicy-fields).

</td>
</tr>

Expand All @@ -116,12 +126,14 @@ Each key in the object is the `__typename` of a type to customize, and the corre
###### `dataIdFromObject`

`Function`

</td>
<td>

**Deprecated.** A function that takes a response object and returns a unique identifier to be used when normalizing the data in the store.

Deprecated in favor of the `keyFields` option of the [`TypePolicy` object](#typepolicy-fields).

</td>
</tr>
</tbody>
Expand Down Expand Up @@ -234,6 +246,91 @@ To disable normalization for a type, define a `TypePolicy` for the type (as show

Objects that are not normalized are instead embedded within their _parent_ object in the cache. You can't access these objects directly, but you can access them via their parent.

## Visualizing the cache

To help understand the structure of your cached data, we strongly recommend installing the [Apollo Client Devtools](../development-testing/developer-tooling/#apollo-client-devtools).

This browser extension includes an inspector that enables you to view all of the normalized objects contained in your cache:

<img src="../img/cache-inspector.jpg" class="screenshot" alt="The Cache tab of the Apollo Client Devtools"></img>

### Example

Let's say we use Apollo Client to run the following query on the [SWAPI demo API](https://github.com/graphql/swapi-graphql):

```graphql
query {
allPeople(first:3) { # Return the first 3 items
people {
id
name
homeworld {
id
name
}
}
}
}
```

This query returns the following result of three `Person` objects, each with a corresponding `homeworld` (a `Planet` object):

<ExpansionPanel title="Click to expand">

```json
{
"data": {
"allPeople": {
"people": [
{
"__typename": "Person",
"id": "cGVvcGxlOjE=",
"name": "Luke Skywalker",
"homeworld": {
"__typename": "Planet",
"id": "cGxhbmV0czox",
"name": "Tatooine"
}
},
{
"__typename": "Person",
"id": "cGVvcGxlOjI=",
"name": "C-3PO",
"homeworld": {
"__typename": "Planet",
"id": "cGxhbmV0czox",
"name": "Tatooine"
}
},
{
"__typename": "Person",
"id": "cGVvcGxlOjM=",
"name": "R2-D2",
"homeworld": {
"__typename": "Planet",
"id": "cGxhbmV0czo4",
"name": "Naboo"
}
}
]
}
}
}
```

</ExpansionPanel>

> Notice that each object in the result includes a `__typename` field, even though our query string _didn't_ include this field. That's because Apollo Client _automatically_ queries for every object's `__typename` field.
After the result is cached, we can view the state of our cache in the Apollo Client Devtools:

<img src="../img/cache-inspector.jpg" class="screenshot" alt="The Cache tab of the Apollo Client Devtools"></img>

Our cache now contains five normalized objects (in addition to the `ROOT_QUERY` object): three `Person` objects and two `Planet` objects.

**Why do we only have two `Planet` objects?** Because two of the three returned `Person` objects have the same `homeworld`. By [normalizing data](#data-normalization) like this, Apollo Client can cache a single copy of an object, and multiple _other_ objects can include _references_ to it (see the `__ref` field of the object in the screenshot above).


## `TypePolicy` fields

To customize how the cache interacts with specific types in your schema, you can provide an object mapping `__typename` strings to `TypePolicy` objects when you create a new `InMemoryCache` object.
Expand Down
Loading

0 comments on commit 2484794

Please sign in to comment.