{"id":13452602,"url":"https://github.com/apollographql/apollo-link-state","last_synced_at":"2025-09-27T08:30:48.101Z","repository":{"id":57108605,"uuid":"108647175","full_name":"apollographql/apollo-link-state","owner":"apollographql","description":"✨ Manage your application's state with Apollo!","archived":true,"fork":false,"pushed_at":"2019-01-17T14:30:21.000Z","size":521,"stargazers_count":1397,"open_issues_count":63,"forks_count":100,"subscribers_count":72,"default_branch":"master","last_synced_at":"2024-12-18T09:46:19.656Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/apollographql.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-28T12:27:47.000Z","updated_at":"2024-10-28T19:25:05.000Z","dependencies_parsed_at":"2022-08-21T04:30:45.172Z","dependency_job_id":null,"html_url":"https://github.com/apollographql/apollo-link-state","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apollographql%2Fapollo-link-state","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apollographql%2Fapollo-link-state/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apollographql%2Fapollo-link-state/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/apollographql%2Fapollo-link-state/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/apollographql","download_url":"https://codeload.github.com/apollographql/apollo-link-state/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":234410609,"owners_count":18828250,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-31T07:01:28.856Z","updated_at":"2025-09-27T08:30:47.309Z","avatar_url":"https://github.com/apollographql.png","language":"TypeScript","funding_links":[],"categories":["TypeScript","Libraries","others","📦 Legacy \u0026 Inactive Projects","Advanced Use Cases"],"sub_categories":["Official Apollo Libraries"],"readme":"# [apollo-link-state](https://www.apollographql.com/docs/link/links/state.html)\n\n\u003e ⚠️ **WARNING** ⚠️\n\u003e \n\u003e Apollo Client 2.5 is going to be released very shortly, and will include integrated local state handling capabilities. The functionality offered by `apollo-link-state` will be included in the Apollo Client core, which means this project/repository will be deprecated. For those interested in trying out the new integrated local state features of AC, see [apollographql/apollo-client#4155](https://github.com/apollographql/apollo-client/pull/4155) (the changes are currently available via `apollo-client@alpha` and `react-apollo@alpha`). We're still in alpha, but will be cutting over to beta soon (so if you have any feedback, please add your comments in [apollographql/apollo-client#4155](https://github.com/apollographql/apollo-client/pull/4155)). Thanks!\n\n\n### Manage your local data with Apollo Client!\n\n[**Docs**](https://www.apollographql.com/docs/link/links/state.html) | [**Announcement Post**](https://dev-blog.apollodata.com/the-future-of-state-management-dd410864cae2) | [**Tutorial Video by Sara Vieira**](https://youtu.be/2RvRcnD8wHY)\n\nManaging remote data from an external API is simple with Apollo Client, but\nwhere do we put all of our data that doesn't fit in that category? Nearly all\napps need some way to centralize client-side data from user interactions and device APIs.\n\nIn the past, Apollo users stored their application's local data in a separate\nRedux or MobX store. With `apollo-link-state`, you no longer have to maintain a\nsecond store for local state. You can instead use the Apollo Client cache as your single source of\ntruth that holds all of your local data alongside your remote data. To access or\nupdate your local state, you use GraphQL queries and mutations just like you\nwould for data from a server.\n\nWhen you use Apollo Client to manage your local state, you get all of the same\nbenefits you know and love like caching and offline persistence without having\nto set these features up yourself. 🎉 On top of that, you also benefit from the [Apollo\nDevTools](https://github.com/apollographql/apollo-client-devtools) for\ndebugging and visibility into your store.\n\n\u003ch2 id=\"start\"\u003eQuick start\u003c/h2\u003e\n\nTo get started, install `apollo-link-state` from npm:\n\n```bash\nnpm install apollo-link-state --save\n```\n\nThe rest of the instructions assume that you have already [set up Apollo\nClient](https://www.apollographql.com/docs/react/basics/setup.html#installation) in your application. After\nyou install the package, you can create your state link by calling\n`withClientState` and passing in a resolver map. A resolver map describes how to\nretrieve and update your local data.\n\nLet's look at an example where we're using a GraphQL mutation to update whether\nour network is connected with a boolean flag:\n\n```js\nimport { withClientState } from 'apollo-link-state';\n\n// This is the same cache you pass into new ApolloClient\nconst cache = new InMemoryCache(...);\n\nconst stateLink = withClientState({\n  cache,\n  resolvers: {\n    Mutation: {\n      updateNetworkStatus: (_, { isConnected }, { cache }) =\u003e {\n        const data = {\n          networkStatus: {\n            __typename: 'NetworkStatus',\n            isConnected\n          },\n        };\n        cache.writeData({ data });\n        return null\n      },\n    },\n  }\n});\n```\n\nTo hook up your state link to Apollo Client, add it to the other links\nin your Apollo Link chain. Your state link should be near the end of the chain, so that other links like `apollo-link-error` can also deal with local state requests. However, it should go before `HttpLink` so local queries and mutations are intercepted\nbefore they hit the network. It should also go before\n[`apollo-link-persisted-queries`](https://github.com/apollographql/apollo-link-persisted-queries)\nif you are using persisted queries. Then, pass your link chain to the Apollo\nClient constructor.\n\n```js\nconst client = new ApolloClient({\n  cache,\n  link: ApolloLink.from([\n    stateLink,\n    new HttpLink()\n  ]),\n});\n```\n\nHow do we differentiate a request for local data from a request that hits our\nserver? In our query or mutation, we specify which fields are client-only with a\n`@client` directive. This tells our network stack to retrieve or update the data\nin the cache with our resolver map that we passed into our state link.\n\n```js\nconst UPDATE_NETWORK_STATUS = gql`\n  mutation updateNetworkStatus($isConnected: Boolean) {\n    updateNetworkStatus(isConnected: $isConnected) @client\n  }\n`;\n```\n\nTo fire off the mutation from your component, bind your mutation to your\ncomponent via your favorite Apollo view layer integration just like you normally\nwould. Here's what this would look like for React:\n\n```js\nconst WrappedComponent = graphql(UPDATE_NETWORK_STATUS, {\n  props: ({ mutate }) =\u003e ({\n    updateNetworkStatus: isConnected =\u003e mutate({ variables: { isConnected } }),\n  }),\n})(NetworkStatus);\n```\n\nWhat if we want to access our network status data from another component? Since\nwe don't know whether our `UPDATE_NETWORK_STATUS` mutation will fire before we\ntry to access the data, we should guard against undefined values by providing a\ndefault state as part of the state link initialization:\n\n```js\nconst stateLink = withClientState({\n  cache,\n  resolvers: {\n    Mutation: {\n      /* same as above */\n    },\n  },\n  defaults: {\n    networkStatus: {\n      __typename: 'NetworkStatus',\n      isConnected: true,\n    }\n  },\n});\n```\n\nThis is the same as calling `writeData` yourself with an initial value:\n\n```js\n// Same as passing defaults above\ncache.writeData({\n  networkStatus: {\n    __typename: 'NetworkStatus',\n    isConnected: true,\n  }\n});\n```\n\nHow do we query the `networkStatus` from our component? Similar to mutations,\njust use a query and the `@client` directive! With Apollo Link, we can combine\ndata sources, including your remote data, in one query.\n\nIn this example, the `articles` field will either hit the cache or fetch from\nour GraphQL endpoint, depending on our fetch policy. Since `networkStatus` is\nmarked with `@client`, we know that this is local data, so it will resolve from\nthe cache.\n\n```js\nconst GET_ARTICLES = gql`\n  query {\n    networkStatus @client {\n      isConnected\n    }\n    articles {\n      id\n      title\n    }\n  }\n`;\n```\n\nTo retrieve the data in your component, bind your query to your component via\nyour favorite Apollo view layer integration just like you normally would. In this case, we'll use React as an example.\nReact Apollo will attach both your remote and local data to `props.data` while\ntracking both loading and error states. Once the query returns a result, your\ncomponent will update reactively. Updates to Apollo Client state via `apollo-link-state` will also automatically update any components using that data in a query.\n\n```js\nconst WrappedComponent = graphql(GET_ARTICLES, {\n  props: ({ data: { networkStatus, articles, loading, error } }) =\u003e {\n    if (loading) {\n      return { loading };\n    }\n\n    if (error) {\n      return { error };\n    }\n\n    return {\n      loading,\n      networkStatus,\n      articles,\n    };\n  },\n})(Articles);\n```\n\nFor more detailed examples, plus in-depth explanations of resolvers, defaults, and more, please check out our official [docs page](https://www.apollographql.com/docs/link/links/state.html).\n\n\u003ch2 id=\"local-development\"\u003eWith Apollo Boost\u003c/h2\u003e\n\nIf you are using `apollo-boost`, it already includes `apollo-link-state` underneath the hood for you.\nInstead of passing the `link` property when instantiating Apollo Client, you pass in `clientState`.\n\n```js\nimport ApolloClient from 'apollo-boost';\n\nconst client = new ApolloClient({\n  clientState: {\n    defaults: {\n      isConnected: true\n    },\n    resolvers: {\n      Mutation: {\n        updateNetworkStatus: (_, { isConnected }, { cache }) =\u003e {\n          cache.writeData({ data: { isConnected }});\n          return null;\n        }\n      }\n    }\n  }\n});\n\n```\n\n\u003ch2 id=\"local-development\"\u003eLocal Development\u003c/h2\u003e\n\nIf you're setting up for local development, and you want to integrate a local\nbranch of `apollo-link-state` into another application, remember that this\nproject is a Lerna monorepo: `./packages/apollo-link-state`\n\nTo link this in, do:\n\n```shell\ncd packages/apollo-link-state \u0026\u0026 yarn link\n```\n\nAnd in your development application do:\n\n```shell\nyarn link apollo-link-state\n```\n\nFinally, each time you make a change in apollo-link-state, you need to run:\n\n```shell\nyarn build \u0026\u0026 yarn bundle\n```\n\nNow you should be good to go!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapollographql%2Fapollo-link-state","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fapollographql%2Fapollo-link-state","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fapollographql%2Fapollo-link-state/lists"}