{"id":21319235,"url":"https://github.com/cdellacqua/stores.js-react-adapter","last_synced_at":"2026-04-28T01:31:46.111Z","repository":{"id":54823566,"uuid":"522324418","full_name":"cdellacqua/stores.js-react-adapter","owner":"cdellacqua","description":"A library that provides React Hooks and components for universal-stores (observable containers of values).","archived":false,"fork":false,"pushed_at":"2024-01-11T20:40:48.000Z","size":492,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-14T23:12:04.454Z","etag":null,"topics":["react","react-hooks","stores"],"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/cdellacqua.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}},"created_at":"2022-08-07T21:04:57.000Z","updated_at":"2022-08-22T20:01:25.000Z","dependencies_parsed_at":"2024-01-12T01:04:10.145Z","dependency_job_id":"79a8a695-23a3-45a8-9f0a-723886b55b43","html_url":"https://github.com/cdellacqua/stores.js-react-adapter","commit_stats":{"total_commits":19,"total_committers":1,"mean_commits":19.0,"dds":0.0,"last_synced_commit":"99eec9dfee15436fcf0f721dfa6a115c565be9a9"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdellacqua%2Fstores.js-react-adapter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdellacqua%2Fstores.js-react-adapter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdellacqua%2Fstores.js-react-adapter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/cdellacqua%2Fstores.js-react-adapter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/cdellacqua","download_url":"https://codeload.github.com/cdellacqua/stores.js-react-adapter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243797519,"owners_count":20349414,"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","stores"],"created_at":"2024-11-21T19:39:35.863Z","updated_at":"2026-04-28T01:31:41.090Z","avatar_url":"https://github.com/cdellacqua.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @universal-stores/react-adapter\n\nA library that provides React Hooks and components for [universal-stores](https://www.npmjs.com/package/universal-stores) (observable containers of values).\n\n[NPM Package](https://www.npmjs.com/package/@universal-stores/react-adapter)\n\n`npm install universal-stores @universal-stores/react-adapter`\n\n(note that you also need `universal-stores`, as that's a peer dependency of this package).\n\n[Documentation](./docs/README.md)\n\n## Hooks\n\n### useStore\n\n`useStore` is designed after `useState`. By calling this hook you'll get a tuple where\nthe first element is the current value contained in the store and the second element\nis a setter/updater.\n\nAs you can see in the following example, the setter accepts both a new value and\nan update function.\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {useStore} from '@universal-stores/react-adapter';\n\nconst count$ = makeStore(0);\n\nfunction Counter() {\n\tconst [count, setCount] = useStore(count$);\n\treturn (\n\t\t\u003c\u003e\n\t\t\t\u003ch1\u003e{count}\u003c/h1\u003e\n\t\t\t\u003cbutton onClick={() =\u003e setCount((c) =\u003e c + 1)}\u003eIncrement\u003c/button\u003e\n\t\t\t\u003cbutton onClick={() =\u003e setCount(0)}\u003eReset\u003c/button\u003e\n\t\t\t\u003cbutton onClick={() =\u003e setCount((c) =\u003e c - 1)}\u003eDecrement\u003c/button\u003e\n\t\t\u003c/\u003e\n\t);\n}\n```\n\n### useReadonlyStore\n\n`useReadonlyStore` returns the value of a store. It can be used with\nboth `ReadonlyStore`s and `Store`s.\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {useReadonlyStore} from '@universal-stores/react-adapter';\n\nconst count$ = makeStore(0);\n\nfunction Counter() {\n\tconst count = useReadonlyStore(count$);\n\treturn (\n\t\t\u003c\u003e\n\t\t\t\u003ch1\u003e{count}\u003c/h1\u003e\n\t\t\u003c/\u003e\n\t);\n}\n```\n\n```tsx\nimport {makeReadonlyStore} from 'universal-stores';\nimport {useReadonlyStore} from '@universal-stores/react-adapter';\n\n// A lazy loaded readonly store that increments its value every second.\nconst autoCount$ = makeReadonlyStore\u003cnumber\u003e(undefined, (set) =\u003e {\n\tlet count = 0;\n\tset(count);\n\tconst intervalId = setInterval(() =\u003e {\n\t\tcount++;\n\t\tset(count);\n\t}, 1000);\n\treturn () =\u003e clearInterval(intervalId);\n});\n\nfunction Counter() {\n\tconst count = useReadonlyStore(autoCount$);\n\treturn (\n\t\t\u003c\u003e\n\t\t\t\u003ch1\u003e{count}\u003c/h1\u003e\n\t\t\u003c/\u003e\n\t);\n}\n```\n\n### useReadonlyStores\n\n`useReadonlyStores` can be used to observe multiple stores at once.\nIt takes an object or an array of `ReadonlyStore`s and/or `Store`s and returns an object or an array of values contained in them.\n\nExample using an object:\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {useReadonlyStores} from '@universal-stores/react-adapter';\n\nconst firstNumber$ = makeStore(4);\nconst secondNumber$ = makeStore(2);\n\nfunction Sum() {\n\tconst {first, second} = useReadonlyStores({\n\t\tfirst: firstNumber$,\n\t\tsecond: secondNumber$,\n\t});\n\treturn (\n\t\t\u003c\u003e\n\t\t\t\u003ch1\u003e{first + second}\u003c/h1\u003e\n\t\t\u003c/\u003e\n\t);\n}\n```\n\nExample using an array\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {useReadonlyStores} from '@universal-stores/react-adapter';\n\nconst firstNumber$ = makeStore(4);\nconst secondNumber$ = makeStore(2);\n\nfunction Sum() {\n\tconst [firstNumber, secondNumber] = useReadonlyStores([\n\t\tfirstNumber$,\n\t\tsecondNumber$,\n\t]);\n\treturn (\n\t\t\u003c\u003e\n\t\t\t\u003ch1\u003e{firstNumber + secondNumber}\u003c/h1\u003e\n\t\t\u003c/\u003e\n\t);\n}\n```\n\n## Components\n\nIf you only need the value of a store in a specific section of your JSX, you\ncan use the following specialized component to optimize the Virtual DOM diffing\nprocess. The following component will make changes affect only a subtree of your main component.\n\n### WithStore\n\nSimilar to `useStore`, it takes a `Store\u003cT\u003e` and a render prop as its children:\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {WithStore} from '@universal-stores/react-adapter';\n\nconst count$ = makeStore(0);\n\nfunction Counter() {\n\treturn (\n\t\t\u003cWithStore store={count$}\u003e\n\t\t\t{(count, setCount) =\u003e (\n\t\t\t\t\u003c\u003e\n\t\t\t\t\t\u003ch1\u003eCounter: {count}\u003c/h1\u003e\n\t\t\t\t\t\u003cbutton onClick={() =\u003e setCount((c) =\u003e c + 1)}\u003eIncrement\u003c/button\u003e\n\t\t\t\t\t\u003cbutton onClick={() =\u003e setCount(0)}\u003eReset\u003c/button\u003e\n\t\t\t\t\t\u003cbutton onClick={() =\u003e setCount((c) =\u003e c - 1)}\u003eDecrement\u003c/button\u003e\n\t\t\t\t\u003c/\u003e\n\t\t\t)}\n\t\t\u003c/WithStore\u003e\n\t);\n}\n```\n\n### WithReadonlyStore\n\nSimilar to `useReadonlyStore`, it takes a `ReadonlyStore\u003cT\u003e` (or a `Store\u003cT\u003e`) and a render prop as its children:\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {WithReadonlyStore} from '@universal-stores/react-adapter';\n\nconst count$ = makeStore(0);\n\nfunction Counter() {\n\treturn (\n\t\t\u003cWithReadonlyStore store={count$}\u003e\n\t\t\t{(count) =\u003e \u003ch1\u003e{count}\u003c/h1\u003e}\n\t\t\u003c/WithReadonlyStore\u003e\n\t);\n}\n```\n\n### WithReadonlyStores\n\nSimilar to `useReadonlyStores`, it takes a collection of `ReadonlyStore\u003cT\u003e`/`Store\u003cT\u003e` and a render prop as its children.\n\nExample using an object:\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {WithReadonlyStores} from '@universal-stores/react-adapter';\n\nconst firstNumber$ = makeStore(4);\nconst secondNumber$ = makeStore(2);\n\nfunction Sum() {\n\treturn (\n\t\t\u003cWithReadonlyStores stores={{first: firstNumber$, second: secondNumber$}}\u003e\n\t\t\t{({first, second}) =\u003e \u003ch1\u003e{first + second}\u003c/h1\u003e}\n\t\t\u003c/WithReadonlyStores\u003e\n\t);\n}\n```\n\nExample using an array:\n\n```tsx\nimport {makeStore} from 'universal-stores';\nimport {WithReadonlyStores} from '@universal-stores/react-adapter';\n\nconst firstNumber$ = makeStore(4);\nconst secondNumber$ = makeStore(2);\n\nfunction Sum() {\n\treturn (\n\t\t\u003cWithReadonlyStores stores={[firstNumber$, secondNumber$]}\u003e\n\t\t\t{([firstNumber, secondNumber]) =\u003e \u003ch1\u003e{firstNumber + secondNumber}\u003c/h1\u003e}\n\t\t\u003c/WithReadonlyStores\u003e\n\t);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdellacqua%2Fstores.js-react-adapter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcdellacqua%2Fstores.js-react-adapter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcdellacqua%2Fstores.js-react-adapter/lists"}