{"id":17109956,"url":"https://github.com/oe/plain-store","last_synced_at":"2026-02-14T16:30:53.358Z","repository":{"id":246409110,"uuid":"821038447","full_name":"oe/plain-store","owner":"oe","description":"A dead simple immutable store for react to manage state in your application, redux alternative in less than 1kb(gzipped).","archived":false,"fork":false,"pushed_at":"2025-03-16T16:17:31.000Z","size":81,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2026-01-13T23:03:26.464Z","etag":null,"topics":["react","redux-alternative","state-management"],"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/oe.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,"zenodo":null}},"created_at":"2024-06-27T17:24:31.000Z","updated_at":"2025-03-16T16:17:34.000Z","dependencies_parsed_at":"2025-04-13T03:37:14.318Z","dependency_job_id":"ddff9d9d-e2b5-4292-80d2-dc6f013965a5","html_url":"https://github.com/oe/plain-store","commit_stats":{"total_commits":23,"total_committers":1,"mean_commits":23.0,"dds":0.0,"last_synced_commit":"65a637aa93d6ad223e09c5c9db27af744b962613"},"previous_names":["oe/plain-store"],"tags_count":17,"template":false,"template_full_name":null,"purl":"pkg:github/oe/plain-store","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oe%2Fplain-store","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oe%2Fplain-store/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oe%2Fplain-store/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oe%2Fplain-store/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oe","download_url":"https://codeload.github.com/oe/plain-store/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oe%2Fplain-store/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29449369,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-14T15:52:44.973Z","status":"ssl_error","status_checked_at":"2026-02-14T15:52:11.208Z","response_time":53,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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","redux-alternative","state-management"],"created_at":"2024-10-14T16:24:56.796Z","updated_at":"2026-02-14T16:30:53.342Z","avatar_url":"https://github.com/oe.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003ch1 align=\"center\"\u003eplain-store\u003c/h1\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003ca href=\"https://github.com/oe/plain-store/actions/workflows/build.yml\"\u003e\n    \u003cimg src=\"https://github.com/oe/template-to-react/actions/workflows/build.yml/badge.svg\" alt=\"Github Workflow\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"#readme\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/%3C%2F%3E-typescript-blue\" alt=\"code with typescript\" height=\"20\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"#readme\"\u003e\n    \u003cimg src=\"https://img.shields.io/badge/coverage-100%25-44CC11\" alt=\"code coverage\" height=\"20\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"#readme\"\u003e\n    \u003cimg src=\"https://badge.fury.io/js/plain-store.svg\" alt=\"npm version\" height=\"20\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.npmjs.com/package/plain-store\"\u003e\n    \u003cimg src=\"https://img.shields.io/npm/dm/plain-store.svg\" alt=\"npm version\" height=\"20\"\u003e\n  \u003c/a\u003e\n\u003c/div\u003e\nA dead simple immutable store for react to manage state in your application, redux alternative in less than 1kb gzipped. Signal like store, no reducer, no context, no provider, no HOC, no epic.\n\n## Installation\n```bash\n# npm\nnpm install plain-store\n# yarn\nyarn add plain-store\n\n```\n\n## Usage\nusing with bundler or es module\n```javascript\nimport { createStore, isDeepEqual } from 'plain-store';\n\nconst initialState = {\n  count: 0\n};\n\nconst store = createStore(initialState);\nstore.set({ count: 1 });\n\nfunction Counter() {\n  const { count } = store.useStore();\n  // derive a new value from the store value\n  const doubled = store.useSelector((state) =\u003e state.count * 2);\n  return (\n    \u003cdiv\u003e\n      \u003cdiv\u003ecount: {count}\u003c/div\u003e\n      \u003cdiv\u003edoubled: {doubled}\u003c/div\u003e\n      \u003cbutton onClick={() =\u003e store.set((prev) =\u003e ({ count: 1 + prev.count }))}\u003eIncrement\u003c/button\u003e\n    \u003c/div\u003e\n  );\n}\n\nstore.get(); // { count: 1 }\nstore.set((prev) =\u003e ({ count: 2 + prev.count })); // { count: 3 }, will trigger Counter re-render\n```\n\nusing with script tag\n```html\n\u003c!-- include react --\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/react/umd/react.production.min.js\"\u003e\u003c/script\u003e\n\u003cscript src=\"https://cdn.jsdelivr.net/npm/plain-store/dist/index.iife.js\"\u003e\u003c/script\u003e\n\u003cscript\u003e\n  const { createStore, isDeepEqual } = PlainStore;\n  const store = createStore({ count: 0 });\n  store.set({ count: 1 });\n\u003c/script\u003e\n```\n\n## API\n### createStore(initialState, options?)\nCreate a store with the initial state.\n```ts\nimport { createStore } from 'plain-store';\n\ninterface ICreateStoreOptions\u003cT\u003e {\n  /**\n   * custom comparator for store value changes, default to `isDeepEqual`\n   * * use it when the default comparator is not working as expected\n   * * `isDeepEqual` works for most cases, but it's not perfect, you can provide a custom comparator to handle the edge cases or performance issues.\n   */\n  comparator?: (a: any, b: any) =\u003e boolean;\n}\n\ninterface ISetStoreOptions {\n  /**\n   * only update the partial value of the store,\n   * * the new value will be merged with the old value\n   */\n  partial?: boolean;\n}\n\ntype ISetStoreOptionsType = boolean | ISetStoreOptions\n\ninterface IStore\u003cT\u003e {\n  // listen to the store value changes, return a function to unsubscribe.\n  subscribe: (listener: () =\u003e void) =\u003e () =\u003e void;\n  // Get the current state of the store, none reactive, could be used anywhere.\n  get: () =\u003e Readonly\u003cT\u003e;\n  // Set the state of the store, could be used anywhere, callback could be async.\n  // * return a promise if the params is async function\n  // * use getStore() to get the latest state of the store when using async function\n  // * use partial option to update the partial value of the store\n  set: (newValue: T | ((prev: T) =\u003e (T | Promise\u003cT\u003e)), cfg?: ISetStoreOptionsType): void | Promise\u003cvoid\u003e\n  // react hook to get the current state of the store.\n  useStore: () =\u003e Readonly\u003cT\u003e;\n  // react hook to select a part of the state.\n  useSelector: \u003cR\u003e(selector: (state: T) =\u003e R) =\u003e Readonly\u003cR\u003e;\n}\nfunction createStore\u003cT\u003e(initialState: T | (() =\u003e T), options?: ICreateStoreOptions\u003cT\u003e): IStore\u003cT\u003e;\n```\n\n```ts\n// always use a new object to update the store value\nstore.set((prev) =\u003e ({ ...prev, newItem: 'xxx' }))\n```\n\n### isDeepEqual(a, b)\nCheck if two values are deeply equal, can efficiently compare common data structures like objects, arrays, regexp, date and primitives.\n```ts\nimport { isDeepEqual } from 'plain-store';\nfunction isDeepEqual(a: any, b: any): boolean;\n```\n\n### isPromiseLike(obj)\nCheck if a value is a promise\n\n```ts\nimport { isPromiseLike } from 'plain-store';\nfunction isPromiseLike(obj: any): boolean;\n```\n\n## License\nMIT\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foe%2Fplain-store","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foe%2Fplain-store","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foe%2Fplain-store/lists"}