Skip to content

Commit

Permalink
Prepare local state section for cache policies + reactive vars
Browse files Browse the repository at this point in the history
  • Loading branch information
hwillson committed Jul 14, 2020
1 parent 8130403 commit 29da64d
Show file tree
Hide file tree
Showing 11 changed files with 59 additions and 11 deletions.
5 changes: 4 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,8 @@
"editor.rulers": [80],
"files.trimTrailingWhitespace": true,
"files.insertFinalNewline": true,
"typescript.tsdk": "../node_modules/typescript/lib"
"typescript.tsdk": "../node_modules/typescript/lib",
"cSpell.enableFiletypes": [
"mdx"
]
}
9 changes: 7 additions & 2 deletions docs/gatsby-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@ module.exports = {
'Fetching data': [
'data/queries',
'data/mutations',
'data/local-state',
'data/subscriptions',
'data/pagination',
'data/fragments',
Expand All @@ -40,7 +39,13 @@ module.exports = {
Caching: [
'caching/cache-configuration',
'caching/cache-field-behavior',
'caching/cache-interaction'],
'caching/cache-interaction'
],
'Local State': [
'local-state/local-state-management',
'local-state/field-policies-reactive-vars',
'local-state/local-resolvers'
],
'Development & Testing': [
'development-testing/static-typing',
'development-testing/testing',
Expand Down
2 changes: 1 addition & 1 deletion docs/source/api/link/apollo-link-schema.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: Assists with mocking and server-side rendering

The schema link provides a [graphql execution environment](http://graphql.org/graphql-js/graphql/#graphql), which allows you to perform GraphQL operations on a provided schema. This type of behavior is commonly used for server-side rendering (SSR) to avoid network calls and mocking data. While the schema link could provide graphql results on the client, currently the graphql execution layer is [too heavy weight](https://bundlephobia.com/result?p=graphql) for practical application.

> To unify your state management with client-side GraphQL operations, refer to Apollo Client's [local state management](../../data/local-state/) functionality. It integrates with the Apollo Client cache and is much more lightweight.
> To unify your state management with client-side GraphQL operations, refer to Apollo Client's [local state management](../../local-state/local-state-management/) functionality. It integrates with the Apollo Client cache and is much more lightweight.
## Installation

Expand Down
2 changes: 1 addition & 1 deletion docs/source/caching/cache-field-behavior.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ const cache = new InMemoryCache({
});
```

> Note that to query for a field that is only defined locally, your query should [include the `@client` directive](/data/local-state/#querying-local-state) on that field so that Apollo Client doesn't include it in requests to your GraphQL server.
> Note that to query for a field that is only defined locally, your query should [include the `@client` directive](../local-state/local-state-management/#querying-local-state) on that field so that Apollo Client doesn't include it in requests to your GraphQL server.
Other use cases for a `read` function include:

Expand Down
2 changes: 1 addition & 1 deletion docs/source/caching/cache-interaction.md
Original file line number Diff line number Diff line change
Expand Up @@ -545,7 +545,7 @@ export default withApollo(graphql(PROFILE_QUERY, {

To register a callback function to be executed after the store has been reset, call `client.onResetStore` and pass in your callback. If you would like to register multiple callbacks, simply call `client.onResetStore` again. All of your callbacks will be pushed into an array and executed concurrently.

In this example, we're using `client.onResetStore` to write default values to the cache. This is useful when using Apollo Client's [local state management](../data/local-state/) features and calling `client.resetStore` anywhere in your application.
In this example, we're using `client.onResetStore` to write default values to the cache. This is useful when using Apollo Client's [local state management](../local-state/local-state-management/) features and calling `client.resetStore` anywhere in your application.

```js
import { ApolloClient, InMemoryCache } from '@apollo/client';
Expand Down
2 changes: 1 addition & 1 deletion docs/source/data/mutations.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -554,5 +554,5 @@ API for performing GraphQL operations. Now that you're familiar with both,
you can begin to take advantage of Apollo Client's full feature set, including:
- [Optimistic UI](../performance/optimistic-ui/): Learn how to improve perceived performance by returning an optimistic response before your mutation result comes back from the server.
- [Local state](local-state/): Use Apollo Client to manage the entirety of your application's local state by executing client-side mutations.
- [Local state](../local-state/local-state-management/): Use Apollo Client to manage the entirety of your application's local state by executing client-side mutations.
- [Caching in Apollo](../caching/cache-configuration/): Dive deep into the Apollo Client cache and how it's normalized. Understanding the cache is helpful when writing update functions for your mutations!
2 changes: 1 addition & 1 deletion docs/source/data/queries.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -451,5 +451,5 @@ Now that you understand how to fetch data with the `useQuery` hook, [learn how t

After that, learn about some other handy Apollo Client features:

- [Local state management](local-state/): Learn how to query local data.
- [Local state management](../local-state/local-state-management/): Learn how to query local data.
- [Pagination](pagination/): Building lists has never been easier thanks to Apollo Client's `fetchMore` function. Learn more in our pagination tutorial.
6 changes: 6 additions & 0 deletions docs/source/local-state/field-policies-reactive-vars.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
title: Field policies and reactive variables
description: Manage and respond to local state changes reactively
---

TODO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
title: Local state management
description: Interact with your local data in Apollo Client
title: Local resolvers
description: Manage local data with GraphQL like resolvers
---

import { MultiCodeBlock } from 'gatsby-theme-apollo-docs';
Expand Down
34 changes: 34 additions & 0 deletions docs/source/local-state/local-state-management.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
---
title: Local state management
description: Interact with your local data in Apollo Client
---

We've learned how to manage remote data from our GraphQL server with Apollo Client, but what should we do with our local data? We want to be able to access boolean flags and device API results from multiple components in our app, but don't want to maintain a separate Redux or MobX store.

Apollo Client provides built-in local state handling capabilities that allow you to access local data by just querying it with GraphQL. You can even request local and server data within the same query. Apollo Client currently supports two approaches for managing local state.

**1. Field policies and reactive variables**

> Available in Apollo Client >= 3.0
Field policies provide a way to customize the reading and writing of individual cache fields. They can be used to modify data on its way into or out of the cache, as well as create virtual client side only `@client` fields. Virtual fields can be integrated into GraphQL queries that are called against the cache, and can perform any unit of work you would like them to (they are driven by simple functions).

Reactive variables are functions that allow you to store local state outside of the cache. Field policies can use them to combine local state with queries read from the cache, but they can also be referenced and updated directly anywhere in your application. Changes made to reactive variables are internally broadcast within Apollo Client, allowing watched queries that use reactive variables to be automatically updated with the newly changed data.

Field policies and reactive variables can be combined in powerful ways to drive an effective client side state management system. Refer to [Field policies and reactive variables](./field-policies-reactive-vars) for more details and local state specific examples.

**2. Local resolvers**

> Available in Apollo Client >= 2.5
Apollo Client supports the use of client side only resolvers, that can be used to fulfil and execute local queries and mutations. Similar to how server side GraphQL resolvers are functions than can be executed to fulfil the fields of a GraphQL query, local resolvers can be used to do the same thing for client side only `@client` fields included in GraphQL queries.

Refer to [Local resolvers](./local-resolvers) for a detailed explanation of how client side resolvers can be used to manage local state.

## ⚠️ Local resolver deprecation

The idea of using client side resolvers to manage local state was first introduced into the Apollo Client ecosystem through the [`apollo-link-state`](https://github.com/apollographql/apollo-link-state) project. The Apollo Client team is always looking for ways to improve local state handling, so we decided to bring local resolver and `@client` support into the Apollo Client core directly, in version 2.5. While managing state with local resolvers works well, the functionality offered by `apollo-link-state`, and then from Apollo Client directly, was originally designed with certain imposed limitations due to its distance from the Apollo Client cache. Apollo Link's don't have direct access to the cache, which means `apollo-link-state` had to implement an approach that couldn't feed or hook into the cache as seamlessly as we would have liked. The local resolver support merged into the Apollo Client core in version 2.5 was essentially a mirror of the Link approach, with a few adjustments to tie into the cache a little more closely. This means Apollo Client's local resolver approach is still a bit limited when it comes to being able to work with the cache more closely, and ultimately providing a better developer experience.

To help address limitations in the local resolver API, we have designed and implemented a new approach for managing local state in Apollo Client 3.0, that works as a direct extension of the cache. Field policies and reactive variables not only help provide a better developer experience from an API use and functionality point of view, but they also improve performance and provide a more reliable foundation for local state management. Re-thinking local state handling with the Apollo Client cache in mind has helped reduce a large number of local state bugs caused by local resolvers being a few too many layers removed from the cache internals.

The [Field policies and reactive variables](./field-policies-reactive-vars) section goes into more detail around what Apollo Client 3's new local state management capabilities look like. We highly recommend reviewing and considering the use of these new API's as a replacement for local resolvers. Local resolvers are still supported in Apollo Client 3, but should be considered deprecated. Local resolver functionality will be removed in a future major version of Apollo Client.
2 changes: 1 addition & 1 deletion docs/source/why-apollo.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ const client = new ApolloClient({ cache });

## Combine local & remote data

Thousands of developers have told us that Apollo Client excels at managing remote data, which equates to roughly 80% of their data needs. But what about local data (like global flags and device API results) that make up the other 20% of the pie? Apollo Client includes [local state management](data/local-state/) features out of the box, that allow you to use your Apollo cache as the single source of truth for data in your application.
Thousands of developers have told us that Apollo Client excels at managing remote data, which equates to roughly 80% of their data needs. But what about local data (like global flags and device API results) that make up the other 20% of the pie? Apollo Client includes [local state management](local-state/local-state-management/) features out of the box, that allow you to use your Apollo cache as the single source of truth for data in your application.

Managing all your data with Apollo Client allows you to take advantage of GraphQL as a unified interface to all of your data. This enables you to inspect both your local and remote schemas in Apollo DevTools through GraphiQL.

Expand Down

0 comments on commit 29da64d

Please sign in to comment.