{"id":13496304,"url":"https://github.com/cvara/rxdb-hooks","last_synced_at":"2025-03-28T18:31:52.691Z","repository":{"id":38023264,"uuid":"244405866","full_name":"cvara/rxdb-hooks","owner":"cvara","description":"React hooks for integrating with RxDB","archived":false,"fork":false,"pushed_at":"2023-08-15T22:24:33.000Z","size":2009,"stargazers_count":123,"open_issues_count":14,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-04-15T07:23:20.802Z","etag":null,"topics":["react","react-hooks","react-rxdb","rxdb","use-rxdb"],"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/cvara.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2020-03-02T15:29:17.000Z","updated_at":"2024-04-11T16:37:49.000Z","dependencies_parsed_at":"2024-01-16T09:54:26.099Z","dependency_job_id":"6012bfb2-102a-4f52-a632-df4af8304f55","html_url":"https://github.com/cvara/rxdb-hooks","commit_stats":{"total_commits":217,"total_committers":5,"mean_commits":43.4,"dds":0.09216589861751157,"last_synced_commit":"db5209324339ead8204d09c865b56a8f38e5547b"},"previous_names":[],"tags_count":20,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvara%2Frxdb-hooks","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvara%2Frxdb-hooks/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvara%2Frxdb-hooks/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cvara%2Frxdb-hooks/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cvara","download_url":"https://codeload.github.com/cvara/rxdb-hooks/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246080670,"owners_count":20720569,"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":["react","react-hooks","react-rxdb","rxdb","use-rxdb"],"created_at":"2024-07-31T19:01:45.543Z","updated_at":"2025-03-28T18:31:51.454Z","avatar_url":"https://github.com/cvara.png","language":"TypeScript","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"readme":"# rxdb-hooks\n\n#### React hooks for integrating with [RxDB](https://github.com/pubkey/rxdb)\n\n\u003ca href=\"https://www.npmjs.com/package/rxdb-hooks\"\u003e\n  \u003cimg src=\"https://img.shields.io/npm/v/rxdb-hooks?color=%23E6008D\u0026style=flat-square\" alt=\"npm version\"\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://circleci.com/gh/cvara/rxdb-hooks/tree/master\"\u003e\n  \u003cimg src=\"https://img.shields.io/circleci/build/github/cvara/rxdb-hooks/master?style=flat-square\" /\u003e\n\u003c/a\u003e\n\n\u003ca href=\"https://codecov.io/gh/cvara/rxdb-hooks\"\u003e\n  \u003cimg src=\"https://img.shields.io/codecov/c/github/cvara/rxdb-hooks?style=flat-square\" /\u003e\n\u003c/a\u003e\n\n\n\u003ca href=\"https://www.npmjs.com/package/rxdb-hooks\"\u003e\n  \u003cimg src=\"https://img.shields.io/npm/dm/rxdb-hooks?color=%233498db\u0026style=flat-square\" alt=\"downloads\"\u003e\n\u003c/a\u003e\n\n\n\n## Table of Contents\n\n\u003cdetails\u003e\n  \u003csummary\u003eClick to expand\u003c/summary\u003e\n\n- [About](#about)\n- [Installation](#installation)\n- [Example](#example)\n- [Compatibility with RxDB](#compatibility-with-rxdb)\n- [Migration Guide](#migration-guide)\n- [API](#api)\n  - [`Provider`](#provider)\n  - [`useRxDB`](#userxdb)\n  - [`useRxCollection`](#userxcollection)\n  - [`useRxQuery`](#userxquery)\n  - [`useRxData`](#userxdata)\n  - [`useRxDocument`](#userxdocument)\n- [Recipes](#recipes)\n  - [Query and Query Constructor memoization](#query-and-query-constructor-memoization)\n  - [Lazy instantiation of RxDatabase \u0026 RxCollections](#lazy-instantiation-of-rxdatabase--rxcollections)\n  - [Mutations](#mutations)\n- [LICENSE](#license)\n\n\u003c/details\u003e\n\n## About\n\nNothing fancy, just conveniently handles common use cases such as:\n\n- subscribing to query observables and translating results into React state\n- cleaning up after subscriptions where necessary\n- paginating results\n- maintaining useful state information (i.e. data fetching or data exhaustion during pagination)\n- lazily creating or destroying collections\n\n## Installation\n\n```bash\n# using npm\nnpm install rxdb-hooks\n\n# using yarn\nyarn add rxdb-hooks\n```\n\n## Example\n\n**Root.jsx**:\n\n```javascript\nimport React, { useEffect } from 'react';\nimport { Provider } from 'rxdb-hooks';\nimport initialize from './initialize';\n\nconst Root = () =\u003e {\n  const [db, setDb] = useState();\n\n  useEffect(() =\u003e {\n    // RxDB instantiation can be asynchronous\n    initialize().then(setDb);\n  }, []);\n\n  // Until db becomes available, consumer hooks that\n  // depend on it will still work, absorbing the delay\n  // by setting their state to isFetching:true\n  return (\n    \u003cProvider db={db}\u003e\n      \u003cApp /\u003e\n    \u003c/Provider\u003e\n  );\n};\n```\n\n**Consumer.jsx**:\n\n```javascript\nimport React from 'react';\nimport { useRxData } from 'rxdb-hooks';\n\nconst Consumer = () =\u003e {\n  const { result: characters, isFetching } = useRxData(\n    // the collection to be queried\n    'characters',\n    // a function returning the query to be applied\n    collection =\u003e\n      collection.find({\n        selector: {\n          affiliation: 'jedi',\n        },\n      })\n  );\n\n  if (isFetching) {\n    return 'loading characters...';\n  }\n\n  return (\n    \u003cul\u003e\n      {characters.map((character, idx) =\u003e (\n        \u003cli key={idx}\u003e{character.name}\u003c/li\u003e\n      ))}\n    \u003c/ul\u003e\n  );\n};\n```\n\n**initialize.js**:\n\n```javascript\nconst initialize = async () =\u003e {\n  // create RxDB\n  const db = await createRxDatabase({\n    name: 'test_database',\n  });\n\n  // create a collection\n  const collection = await db.addCollections({\n    characters: {\n      schema: {\n        title: 'characters',\n        version: 0,\n        type: 'object',\n        primaryKey: 'id',\n        properties: {\n          id: {\n            type: 'string',\n            maxLength: 100,\n          },\n          name: {\n            type: 'string',\n          },\n        },\n      },\n    },\n  });\n\n  // maybe sync collection to a remote\n  // ...\n\n  return db;\n};\n```\n\n## Compatibility with RxDB\n\nThe core API of rxdb-hooks remains largely the same across all major versions _beyond_ `1.x`, however some parts of the internal\nimplementation (most notably [the plugin](src/plugins.ts)) differ based on the version of rxdb we need to target **\\***.\nPlease use the appropriate version of rxdb-hooks as per this table:\n\n| rxdb-hooks version | targeted RxDB version  |\n| ------------------ | ---------------------- |\n| `5.x`              | `14.x`                 |\n| `4.1.x`            | `13.x`                 |\n| `4.0.x`            | `10.x`, `11.x`, `12.x` |\n| `3.x`              | `9.x`                  |\n| `1.x`, `2.x`       | `8.x`                  |\n\n_\\* Versions 7.x of RxDB and below have not been tested and are not guaranteed to work with rxdb-hooks_\n\n## Migration Guide\n\n### `4.x` =\u003e `5.x`\n\n- `useRxDocument` has been dropped; for fetching single documents simply use `useRxQuery` or `useRxData`\n- observing lazily created collection has become an opt-in feature that, if needed, has to be explicitly enabled by using the provided plugin. For more info see [Lazy instantiation of RxDatabase \u0026 RxCollections](#lazy-instantiation-of-rxdatabase--rxcollections)\n\n## API\n\n### `Provider`\n\nThe `\u003cProvider /\u003e` makes the RxDatabase instance available to nested components and is required for all subsequent hooks to work.\n\n#### Props\n\n| Property | Type         | Description                                  |\n| -------- | ------------ | -------------------------------------------- |\n| `db`     | `RxDatabase` | the RxDatabase instance to consume data from |\n\n\u003chr /\u003e\n\n### `useRxDB`\n\nReturns the RxDatabase instance made available by the `\u003cProvider /\u003e`\n\n```javascript\nfunction useRxDB(): RxDatabase\n```\n\n#### Example\n\n```javascript\nconst db = useRxDB();\n```\n\n\u003chr /\u003e\n\n### `useRxCollection`\n\nGiven a collection name returns an RxCollection instance, if found in RxDatabase.\n\n```javascript\nfunction useRxCollection\u003cT\u003e(name: string): RxCollection\u003cT\u003e | null\n```\n\n#### Example\n\n```javascript\nconst collection = useRxCollection('characters');\n```\n\n\u003chr /\u003e\n\n### `useRxQuery`\n\nSubscribes to given RxQuery object providing query results and some helpful extra state variables.\n\n```javascript\nfunction useRxQuery\u003cT\u003e(query: RxQuery, options?: UseRxQueryOptions): RxQueryResult\u003cT\u003e\n```\n\n#### `options: UseRxQueryOptions`\n\n| Option       | Type                          | Description                                                                                                                                                                                                                                                                                                                                     |\n| ------------ | ----------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| `pageSize`   | `number`                      | (optional) enables pagination \u0026 defines page limit                                                                                                                                                                                                                                                                                              |\n| `pagination` | `\"Traditional\" \\| \"Infinite\"` | (optional) determines pagination mode: \u003cbr\u003e`Traditional`: results are split into pages, starts by rendering the first page and total `pageCount` is returned, allowing for requesting results of any specific page. \u003cbr\u003e`Infinite`: first page of results is rendered, allowing for gradually requesting more. \u003cbr\u003e**Default**: `\"Traditional\"` |\n| `json`       | `boolean`                     | (optional) when `true` resulting documents will be converted to plain JavaScript objects; equivalent to manually calling `.toJSON()` on each `RxDocument`. **Default**: `false`                                                                                                                                                                 |\n\n#### `result: RxQueryResult\u003cT\u003e`\n\n| Property      | Type                     | Description                                                                                                            |\n| ------------- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------- |\n| `result`      | `T[] \\| RxDocument\u003cT\u003e[]` | the resulting array of objects or `RxDocument` instances, depending on `json` option                                   |\n| `isFetching`  | `boolean`                | fetching state indicator                                                                                               |\n| `currentPage` | `number`                 | relevant in **all** pagination modes; holds number of current page                                                     |\n| `isExhausted` | `boolean`                | relevant in **Infinite** pagination; flags result list as \"exhausted\", meaning all documents have been already fetched |\n| `fetchMore`   | `() =\u003e void`             | relevant in **Infinite** pagination; a function to be called by the consumer to request documents of the next page     |\n| `resetList`   | `() =\u003e void`             | relevant in **Infinite** pagination; a function to be called by the consumer to reset paginated results                |\n| `pageCount`   | `number`                 | relevant in **Traditional** pagination; holds the total number of pages available                                      |\n| `fetchPage`   | `(page: number) =\u003e void` | relevant in **Traditional** pagination; a function to be called by the consumer to request results of a specific page  |\n\n#### Simple Example\n\n```javascript\nconst collection = useRxCollection('characters');\n\nconst query = collection.find().where('affiliation').equals('Jedi');\n\nconst { result } = useRxQuery(query);\n```\n\n#### Infinite Scroll Pagination Example\n\n```javascript\nconst collection = useRxCollection('characters');\n\nconst query = collection.find().where('affiliation').equals('Jedi');\n\nconst {\n  result: characters,\n  isFetching,\n  fetchMore,\n  isExhausted,\n} = useRxQuery(query, {\n  pageSize: 5,\n  pagination: 'Infinite',\n});\n\nif (isFetching) {\n  return 'Loading...';\n}\n\nreturn (\n  \u003cCharacterList\u003e\n    {characters.map((character, index) =\u003e (\n      \u003cCharacter character={character} key={index} /\u003e\n    ))}\n    {!isExhausted \u0026\u0026 \u003cbutton onClick={fetchMore}\u003eload more\u003c/button\u003e}\n  \u003c/CharacterList\u003e\n);\n```\n\n#### Traditional Pagination Example\n\n```javascript\nconst collection = useRxCollection('characters');\n\nconst query = collection.find({\n  selector: {\n    affiliation: 'Jedi',\n  },\n});\n\nconst {\n  result: characters,\n  isFetching,\n  fetchPage,\n  pageCount,\n} = useRxQuery(query, {\n  pageSize: 5,\n  pagination: 'Traditional',\n});\n\nif (isFetching) {\n  return 'Loading...';\n}\n\n// render results and leverage pageCount to render page navigation\nreturn (\n  \u003cdiv\u003e\n    \u003cCharacterList\u003e\n      {characters.map((character, index) =\u003e (\n        \u003cCharacter character={character} key={index} /\u003e\n      ))}\n    \u003c/CharacterList\u003e\n    \u003cdiv\u003e\n      {Array(pageCount)\n        .fill()\n        .map((x, i) =\u003e (\n          \u003cbutton\n            onClick={() =\u003e {\n              fetchPage(i + 1);\n            }}\n          \u003e\n            page {i + 1}\n          \u003c/button\u003e\n        ))}\n    \u003c/div\u003e\n  \u003c/div\u003e\n);\n```\n\n\u003chr /\u003e\n\n### `useRxData`\n\nConvenience wrapper around `useRxQuery` that expects a collection name \u0026 a query constructor function\n\n```javascript\nfunction useRxData\u003cT\u003e(\n\tcollectionName: string,\n\tqueryConstructor: ((collection: RxCollection\u003cT\u003e) =\u003e RxQuery\u003cT\u003e | undefined) | undefined,\n\toptions?: UseRxQueryOptions\n): RxQueryResult\u003cT\u003e\n```\n\n#### Example\n\n```javascript\nconst { result } = useRxData('characters', collection =\u003e\n  collection.find().where('affiliation').equals('Jedi')\n);\n```\n\n\u003chr /\u003e\n\n## Recipes\n\n### Query and Query Constructor memoization\n\nBy design, `useRxQuery` will re-subscribe to `query` object whenever it changes, allowing\nfor query criteria to be modified during component updates. For this reason, to\navoid unnecessary re-subscriptions, query should be memoized (i.e. via react's `useMemo`):\n\n```javascript\nconst { affiliation } = props;\nconst collection = useRxCollection('characters');\n\nconst query = useMemo(\n  () =\u003e\n    collection.find({\n      selector: {\n        affiliation,\n      },\n    }),\n  [collection, affiliation]\n);\n\nconst { result } = useRxQuery(query);\n```\n\nSame goes for `useRxData` and the `queryConstructor` function:\n\n```javascript\nconst { affiliation } = props;\n\nconst queryConstructor = useCallback(\n  collection =\u003e\n    collection.find({\n      selector: {\n        affiliation,\n      },\n    }),\n  [affiliation]\n);\n\nconst { result } = useRxData('characters', queryConstructor);\n```\n\n### Lazy instantiation of RxDatabase \u0026 RxCollections\n\nAll rxdb-hooks give you the ability to lazily instantiate the database and the\ncollections within it. Initial delay until the above become available is absorbed\nby indicating the state as fetching (`isFetching:true`).\n\nSince `v5.0.0` of `rxdb-hooks`, observing newly created collections has become\nan **opt-in** feature that, _if needed_, has to be enabled via the provided `observeNewCollections` plugin:\n\n```javascript\nimport { addRxPlugin } from 'rxdb';\nimport { observeNewCollections } from 'rxdb-hooks';\n\naddRxPlugin(observeNewCollections);\n```\n\nAdding the plugin makes it possible for all rxdb-hooks to pick up data from\ncollections that are lazily added after the inital db initialization.\n\nAlso note that lazily instantiating the rxdb instance itself is supported\nout-of-the-box, **the plugin only affects lazy collection creation**.\n\n### Mutations\n\nPerforming mutations on data is possible through the APIs provided by [RxDocument](https://rxdb.info/rx-document.html#functions)\nand [RxCollection](https://rxdb.info/rx-collection.html#functions):\n\n#### Example\n\n```javascript\nconst collection = useRxCollection('characters');\n\ncollection.upsert({\n  name: 'Luke Skywalker',\n  affiliation: 'Jedi',\n});\n```\n\n## LICENSE\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcvara%2Frxdb-hooks","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcvara%2Frxdb-hooks","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcvara%2Frxdb-hooks/lists"}