{"id":26255090,"url":"https://github.com/patlux/react-query-cache-persistent","last_synced_at":"2025-03-13T19:17:29.151Z","repository":{"id":245363158,"uuid":"818311585","full_name":"patlux/react-query-cache-persistent","owner":"patlux","description":"Persist your queries in a simple and performant way","archived":false,"fork":false,"pushed_at":"2024-08-18T21:41:46.000Z","size":103,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-07T01:47:22.654Z","etag":null,"topics":["cache","persistent","query","react-query"],"latest_commit_sha":null,"homepage":"https://patwoz.dev","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/patlux.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-21T15:03:45.000Z","updated_at":"2024-10-23T11:23:40.000Z","dependencies_parsed_at":"2024-06-21T20:06:10.341Z","dependency_job_id":null,"html_url":"https://github.com/patlux/react-query-cache-persistent","commit_stats":null,"previous_names":["patlux/react-query-cache-persistent"],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patlux%2Freact-query-cache-persistent","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patlux%2Freact-query-cache-persistent/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patlux%2Freact-query-cache-persistent/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/patlux%2Freact-query-cache-persistent/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/patlux","download_url":"https://codeload.github.com/patlux/react-query-cache-persistent/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243467024,"owners_count":20295309,"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":["cache","persistent","query","react-query"],"created_at":"2025-03-13T19:17:28.448Z","updated_at":"2025-03-13T19:17:29.128Z","avatar_url":"https://github.com/patlux.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# react-query-cache-persistent\n\nThis persistor extends [QueryCache](https://tanstack.com/query/v5/docs/reference/QueryCache) to persist the cache in a simple way without hydration/dehydration phase.\n\nThe biggest advantage in terms of performance is, that the persistor stores the queries by each single query instead of storing the whole cache on each change.\n\nThis is huge if your cache is several megabytes in size.\n\n\u003e ⚠️  The only drawback is that this only works in a synchronous way. You cannot use this if your storage only provides asynchronous methods to get/set the cache. See [How it works](#how-it-works)\n\n## Usage\n\nSee [below for examples](#examples).\n\n```ts\nimport { PersistentQueryCache } from 'react-query-cache-persistent'\n\n// Your implementation. See below for examples.\nconst persistentQueryCache = new PersistentQueryCache({\n  add: (query) =\u003e {},\n  updated: (query) =\u003e {},\n  removed: (query) =\u003e {},\n})\n\nconst queryClient = new QueryClient({ queryCache: persistentQueryCache })\n```\n\n## Examples\n\n### Web\n\nUses `localStorage` as storage.\n\n![localStorage](https://github.com/patlux/react-query-cache-persistent/assets/4481570/5c7c1ebf-9c94-4171-b411-224debe1b7fb)\n\n```ts\nimport { PersistentQueryCache } from 'react-query-cache-persistent'\n\nconst persistentQueryCache = new PersistentQueryCache({\n  add: (query) =\u003e {\n    const item = window.localStorage.getItem(`queryCache.${query.queryHash}`)\n\n    if (item != null) {\n      query.state = JSON.parse(item)\n    }\n\n    window.localStorage.setItem(`queryCache.${query.queryHash}`, JSON.stringify(query.state))\n  },\n  updated: (query) =\u003e {\n    window.localStorage.setItem(`queryCache.${query.queryHash}`, JSON.stringify(query.state))\n  },\n  removed: (query) =\u003e {\n    window.localStorage.removeItem(`queryCache.${query.queryHash}`)\n  },\n})\n\nconst queryClient = new QueryClient({ queryCache: persistentQueryCache })\n```\n\n### React Native\n\nUses `@op-engineering/op-sqlite` as storage. But you can use any sqlite solution as long it supports synchronous get/set.\n\nThe example below writes each query as a table row into a sqlite database\n\n![queryCache.sqlite3](https://github.com/patlux/react-query-cache-persistent/assets/4481570/8913de2a-4af8-46e1-858f-478d8ce9914d)\n\n```ts\nimport {\n  ANDROID_DATABASE_PATH,\n  IOS_LIBRARY_PATH,\n  PreparedStatementObj,\n  open,\n} from '@op-engineering/op-sqlite'\nimport { Query } from '@tanstack/react-query'\nimport { Platform } from 'react-native'\n\nimport { PersistentQueryCache } from 'react-query-cache-persistent'\n\nconst tableName = 'queryCache'\n\nconst connect = () =\u003e {\n  return open({\n    name: 'queryCache.sqlite3',\n    location: Platform.OS === 'ios' ? IOS_LIBRARY_PATH : ANDROID_DATABASE_PATH,\n  })\n}\n\nlet db = connect()\n\ndb.execute(\n  `CREATE TABLE IF NOT EXISTS ${tableName} (queryHash TEXT NOT NULL UNIQUE, queryState TEXT) STRICT;`\n)\n\nconst selectStmt = db.prepareStatement(`SELECT queryState FROM ${tableName} WHERE queryHash = ?;`)\nconst insertStmt = db.prepareStatement(\n  `INSERT INTO ${tableName} (queryHash, queryState) VALUES (?, ?) ON CONFLICT(queryHash) DO UPDATE SET queryState=excluded.queryState;`\n)\nconst deleteStmt = db.prepareStatement(`DELETE FROM ${tableName} WHERE queryHash = ?;`)\n\n/**\n * Executes the prepared statement with the given parameters\n *\n * Will retry once if it throws `[OP-SQLite] DB is not open`\n */\nconst runStmt = (stmt: PreparedStatementObj, params: string[]) =\u003e {\n  try {\n    stmt.bind(params)\n    return stmt.execute()\n  } catch (error: unknown) {\n    if (`${error}`.includes('[OP-SQLite] DB is not open')) {\n      // retry once (on iOS the first execution fails on first start, but only in the context of PersistQueryCache::add)\n      db = connect()\n      stmt.bind(params)\n      const result = stmt.execute()\n      console.warn(`First execution failed. Second try worked.`)\n      return result\n    }\n    console.warn(`Failed to execute query: \"${error}\".`)\n    throw error\n  }\n}\n\nexport const queryCache = new PersistentQueryCache({\n  add: (query: Query) =\u003e {\n    const result = runStmt(selectStmt, [query.queryHash])\n\n    const firstRow = result.rows?._array[0]\n    if (firstRow != null) {\n      try {\n        query.state = JSON.parse(firstRow.queryState)\n      } catch (error: unknown) {\n        console.warn(`Failed to hydrate state for query \"${query.queryHash}\": ${error}`)\n      }\n    }\n\n    runStmt(insertStmt, [query.queryHash, JSON.stringify(query.state)])\n  },\n\n  updated: (query: Query) =\u003e {\n    runStmt(insertStmt, [query.queryHash, JSON.stringify(query.state)])\n  },\n\n  removed: (query: Query) =\u003e {\n    runStmt(deleteStmt, [query.queryHash])\n  },\n})\n```\n\n\n\n\n# How it works\n\n\u003e TODO\n\n# License\n\nMIT License.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatlux%2Freact-query-cache-persistent","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpatlux%2Freact-query-cache-persistent","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpatlux%2Freact-query-cache-persistent/lists"}