{"id":20611911,"url":"https://github.com/jimmyn/apollo-client","last_synced_at":"2025-04-15T05:42:57.901Z","repository":{"id":41785747,"uuid":"232766671","full_name":"jimmyn/apollo-client","owner":"jimmyn","description":"Apollo React Hooks with automatic cache updates","archived":false,"fork":false,"pushed_at":"2023-01-07T13:32:49.000Z","size":1148,"stargazers_count":3,"open_issues_count":11,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-15T05:42:50.857Z","etag":null,"topics":["apollo","apollo-react","apollo-react-hooks","react","react-hooks"],"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/jimmyn.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2020-01-09T09:03:26.000Z","updated_at":"2022-03-03T10:17:05.000Z","dependencies_parsed_at":"2023-02-07T07:42:37.105Z","dependency_job_id":null,"html_url":"https://github.com/jimmyn/apollo-client","commit_stats":null,"previous_names":["jimmyn/apollo-offline-hooks"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmyn%2Fapollo-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmyn%2Fapollo-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmyn%2Fapollo-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jimmyn%2Fapollo-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jimmyn","download_url":"https://codeload.github.com/jimmyn/apollo-client/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249016307,"owners_count":21198828,"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":["apollo","apollo-react","apollo-react-hooks","react","react-hooks"],"created_at":"2024-11-16T10:22:34.942Z","updated_at":"2025-04-15T05:42:57.882Z","avatar_url":"https://github.com/jimmyn.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Apollo Client\n\nA drop-in replacement\nfor [@apollo/client](https://www.apollographql.com/docs/react/get-started/) with automatic cache\nupdates. It will update apollo cache based on a mutation or subscription result.\n\n## Install\n\n```\nnpm i @jimmyn/apollo-client @apollo/client --save\n```\n\nor\n\n```\nyarn add @jimmyn/apollo-client @apollo/client\n```\n\n## Setup\n\n```typescript jsx\nimport React from 'react';\nimport {render} from 'react-dom';\nimport {ApolloClient, InMemoryCache} from '@jimmyn/apollo-client';\n\nconst client = new ApolloClient({\n  uri: 'localhost:8080',\n  cache: new InMemoryCache()\n});\n\nconst App = () =\u003e (\n  \u003cApolloProvider client={client}\u003e\n    \u003cdiv\u003e\n      \u003ch2\u003eMy first Apollo app 🚀\u003c/h2\u003e\n    \u003c/div\u003e\n  \u003c/ApolloProvider\u003e\n);\n\nrender(\u003cApp /\u003e, document.getElementById('root'));\n```\n\n## Mutations\n\nThis package\nextends [useMutation](https://www.apollographql.com/docs/react/api/react/hooks/#options-2) options\nallowing to update cached queries in one line of code instead of writing complex `update` functions.\n\nFor example this code\n\n```typescript jsx\nimport React from 'react';\nimport {useMutation, useQuery} from '@jimmyn/apollo-client';\nimport {createTodoMutation, todosQuery} from './api/operations';\nimport {TodosList} from './TodosList';\n\nexport const Todos = () =\u003e {\n  const {data} = useQuery(todosQuery);\n  const todos = data?.todos || [];\n\n  const [createTodo] = useMutation(createTodoMutation, {\n    updateQuery: todosQuery // \u003c== pass a gql query you want to update\n  });\n\n  const handleCreateTodo = () =\u003e {\n    return createTodo({\n      variables: {\n        task: 'New todo',\n        createdAt: new Date().toISOString()\n      }\n    });\n  };\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={handleCreateTodo}\u003eCreate todo\u003c/button\u003e\n      \u003cTodosList todos={todos} /\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\nis equivalent to\n\n```typescript jsx\nimport React from 'react';\nimport {useMutation, useQuery} from '@apollo/react-hooks';\nimport {createTodoMutation, todosQuery} from './api/operations';\nimport {TodosList} from './TodosList';\n\nexport const Todos = () =\u003e {\n  const {data} = useQuery(todosQuery);\n  const todos = data?.todos || [];\n\n  const [createTodo] = useMutation(createTodoMutation);\n\n  const handleCreateTodo = () =\u003e {\n    return createTodo({\n      variables: {\n        task: 'New todo',\n        createdAt: new Date().toISOString()\n      },\n      update: (proxy, {data}) =\u003e {\n        const newTodo = data.createTodo;\n        try {\n          const cache = proxy.readQuery({query: todosQuery});\n          proxy.writeQuery({\n            query: todosQuery,\n            data: {\n              todos: [...cache.todos, newTodo]\n            }\n          });\n        } catch (error) {\n          console.log(error);\n        }\n      }\n    });\n  };\n\n  return (\n    \u003cdiv\u003e\n      \u003cbutton onClick={handleCreateTodo}\u003eCreate todo\u003c/button\u003e\n      \u003cTodosList todos={todos} /\u003e\n    \u003c/div\u003e\n  );\n};\n```\n\nAnd this code\n\n```typescript jsx\nimport React from 'react';\nimport {useMutation} from '@jimmyn/apollo-client';\nimport {Todo} from './api/generated';\nimport {deleteTodoMutation, todosQuery, updateTodoMutation} from './api/operations';\n\ntype Props = {\n  todo: Todo;\n};\n\nexport const Todo: React.FC\u003cProps\u003e = ({todo}) =\u003e {\n  const [deleteTodo] = useMutation(deleteTodoMutation, {\n    updateQuery: todosQuery,\n\n    // to delete an item we need to provide it's id\n    // if our api simply returns true when item is deleted\n    // we need to return an id explicitly\n    mapResultToUpdate: data =\u003e todo\n  });\n  const [updateTodo] = useMutation(updateTodoMutation);\n\n  const handleDeleteTodo = () =\u003e {\n    return deleteTodo({\n      variables: {id: todo.id}\n    });\n  };\n\n  const handleUpdateTodo = () =\u003e {\n    return updateTodo({\n      variables: {id: todo.id, done: !todo.done}\n    });\n  };\n\n  return (\n    \u003cli\u003e\n      \u003cinput type=\"checkbox\" checked={todo.done} onChange={handleUpdateTodo} /\u003e\n      {todo.task}\n      \u003cbutton onClick={handleDeleteTodo}\u003edelete\u003c/button\u003e\n    \u003c/li\u003e\n  );\n};\n```\n\nis equivalent to\n\n```typescript jsx\nimport React from 'react';\nimport {useMutation} from '@apollo/react-hooks';\nimport {Todo} from './api/generated';\nimport {deleteTodoMutation, todosQuery, updateTodoMutation} from './api/operations';\n\ntype Props = {\n  todo: Todo;\n};\n\nexport const Todo: React.FC\u003cProps\u003e = ({todo}) =\u003e {\n  const [deleteTodo] = useMutation(deleteTodoMutation);\n  const [updateTodo] = useMutation(updateTodoMutation);\n\n  const handleDeleteTodo = () =\u003e {\n    return deleteTodo({\n      variables: {id: todo.id},\n      update: proxy =\u003e {\n        try {\n          const cache = proxy.readQuery({query: todosQuery});\n          proxy.writeQuery({\n            query: todosQuery,\n            data: {\n              todos: cache.todos.filter(item =\u003e item.id !== todo.id)\n            }\n          });\n        } catch (error) {\n          console.log(error);\n        }\n      }\n    });\n  };\n\n  const handleUpdateTodo = () =\u003e {\n    // apollo client is clever enough to update an item in cache\n    // although if you want to update an item with different type you'll have to write\n    // a manual update function\n    return updateTodo({\n      variables: {id: todo.id, done: !todo.done}\n    });\n  };\n\n  return (\n    \u003cli\u003e\n      \u003cinput type=\"checkbox\" checked={todo.done} onClick={handleUpdateTodo} /\u003e\n      {todo.task}\n      \u003cbutton onClick={handleDeleteTodo}\u003edelete\u003c/button\u003e\n    \u003c/li\u003e\n  );\n};\n```\n\n## `useMutation` offline options\n\n| Option              | Description                                                                                                                                                                                                                                                                          | Default               |\n| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------- |\n| `updateQuery`       | A graphql query (wrapped in `gql` tag) that should be updated. You can pass query directly or specify it with variables `{query: todosQuery, variables: {limit: 10}}`                                                                                                                |\n| `updatePath`        | Overrides a path inside the query where the item should be updated. For example if your query has structure like `{items: [...], total: 10}`, you can specify `updatePath: ['items']`. In most cases it is automatically detected. Pass `[]` to update data in the root query object |\n| `idField`           | Unique field that is used to find the item in cache. It should be present in the mutation response                                                                                                                                                                                   | `id`                  |\n| `operationType`     | Indicates what type of the operation should be performed e.g. add/remove/update item. By default operation type is automatically detected from mutation name e.g. `createTodo` will result in `OperationTypes.ADD`.                                                                  | `OperationTypes.AUTO` |\n| `mapResultToUpdate` | A function that receives mutation result and returns an updated item. Function result should contain at least an id field                                                                                                                                                            |\n\n[Other `useMutation` hook options](https://www.apollographql.com/docs/react/api/react/hooks/#options-2)\n\nOffline options can be passed to the `useMutation` hook or to the mutation function directly.\n\n```typescript jsx\nconst [deleteTodo] = useMutation(deleteTodoMutation, {\n  updateQuery: todosQuery,\n  mapResultToUpdate: data =\u003e todo\n});\n\nconst handleDeleteTodo = () =\u003e {\n  return deleteTodo({\n    variables: {id: todo.id}\n  });\n};\n```\n\nis the same as\n\n```typescript jsx\nconst [deleteTodo] = useMutation(deleteTodoMutation);\n\nconst handleDeleteTodo = () =\u003e {\n  return deleteTodo({\n    variables: {id: todo.id},\n    updateQuery: todosQuery,\n    mapResultToUpdate: data =\u003e todo\n  });\n};\n```\n\n## Subscriptions\n\n`useSubscription` accepts the same offline options as `useMutation`\n\n```typescript jsx\nuseSubscription(onTodoUpdate, {updateQuery: todosQuery});\n```\n\n[Other `useSubscription` hook options](https://www.apollographql.com/docs/react/api/react/hooks/#options-3)\n\n## Customize default configurations\n\nDefault configurations can be customized by calling `setOfflineConfig`\n\n```typescript jsx\nimport {setOfflineConfig} from '@jimmyn/apollo-client';\n\nsetOfflineConfig({\n  getIdFieldFromObject(item: any) {\n    switch (item.__typename) {\n      case 'Todo':\n        return 'id';\n      case 'User':\n        return 'user_id';\n    }\n  }\n});\n```\n\n## Configuration options\n\n| Option                 | Description                                                                                                          | Default                               |\n| ---------------------- | -------------------------------------------------------------------------------------------------------------------- | ------------------------------------- |\n| `idField`              | Unique field that is used to find the item in cache. It should be present in the mutation response                   | `id`                                  |\n| `getIdFieldFromObject` | A function that receives updated item and returns an id field name. If defined it will tke precedence over `idField` |\n| `prefixesForRemove`    | A list of mutation name prefixes that will result in remove operation                                                | [prefixesForRemove](src/const.ts#L8)  |\n| `prefixesForUpdate`    | A list of mutation name prefixes that will result in update operation                                                | [prefixesForUpdate](src/const.ts#L19) |\n| `prefixesForAdd`       | A list of mutation name prefixes that will result in add operation                                                   | [prefixesForAdd](src/const.ts#L32)    |\n\n## Update Apollo cache directly\n\nThis package also exposes `updateApolloCache` function directly, that can be used to build custom\nimplementations\n\nExample\n\n```typescript\nimport {updateApolloCache} from '@jimmyn/apollo-client';\n\nconst newTodo = {\n  __typename: 'Todo',\n  id: 1,\n  task: 'New todo',\n  done: false,\n  createdAt: new Date().toISOString()\n};\n\nupdateApolloCache({\n  client,\n  data: {createTodo: newTodo},\n  updateQuery: todosQuery\n});\n```\n\nFunction signature\n\n```typescript\ntype OfflineOptions\u003cTData\u003e = {\n  updateQuery?: QueryWithVariables | DocumentNode;\n  idField?: string;\n  operationType?: OperationTypes;\n  mapResultToUpdate?(data: NonNullable\u003cTData\u003e): Item;\n};\n\ntype UpdateCacheOptions\u003cTData = any\u003e = OfflineOptions\u003cTData\u003e \u0026 {\n  client: ApolloClient\u003cany\u003e | DataProxy;\n  data: TData;\n};\n\nconst updateApolloCache: \u003cTData = any\u003e({\n  client,\n  data,\n  idField,\n  updateQuery,\n  operationType,\n  mapResultToUpdate\n}: UpdateCacheOptions\u003cTData\u003e) =\u003e void;\n```\n\n## Credits\n\nThis package is based\non [Amplify Offline Helpers](https://github.com/awslabs/aws-mobile-appsync-sdk-js/blob/master/OFFLINE_HELPERS.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimmyn%2Fapollo-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjimmyn%2Fapollo-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjimmyn%2Fapollo-client/lists"}