{"id":13902873,"url":"https://github.com/Dynalon/reactive-state","last_synced_at":"2025-07-18T00:32:28.545Z","repository":{"id":21205579,"uuid":"91882121","full_name":"Dynalon/reactive-state","owner":"Dynalon","description":"Redux-clone build with strict typing and RxJS down to its core. Wrist-friendly, no boilerplate or endless switch statements","archived":false,"fork":false,"pushed_at":"2023-02-27T16:30:48.000Z","size":1390,"stargazers_count":137,"open_issues_count":9,"forks_count":7,"subscribers_count":11,"default_branch":"master","last_synced_at":"2024-04-15T07:39:44.606Z","etag":null,"topics":["functional-reactive-programming","react-redux","redux","rxjs","state-management","typescript"],"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/Dynalon.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,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-05-20T10:34:40.000Z","updated_at":"2024-07-10T16:17:31.925Z","dependencies_parsed_at":"2024-07-14T12:02:28.461Z","dependency_job_id":null,"html_url":"https://github.com/Dynalon/reactive-state","commit_stats":null,"previous_names":[],"tags_count":79,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynalon%2Freactive-state","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynalon%2Freactive-state/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynalon%2Freactive-state/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Dynalon%2Freactive-state/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Dynalon","download_url":"https://codeload.github.com/Dynalon/reactive-state/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":214260308,"owners_count":15707075,"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":["functional-reactive-programming","react-redux","redux","rxjs","state-management","typescript"],"created_at":"2024-08-06T22:01:28.694Z","updated_at":"2024-08-06T22:04:17.224Z","avatar_url":"https://github.com/Dynalon.png","language":"TypeScript","readme":"[![Build Status](https://travis-ci.org/Dynalon/reactive-state.svg?branch=master)](https://travis-ci.org/Dynalon/reactive-state)\n[![npm version](https://badge.fury.io/js/reactive-state.svg)](https://badge.fury.io/js/reactive-state)\n![code coverage](https://coveralls.io/repos/Dynalon/reactive-state/badge.svg?branch=master\u0026service=github)\n\nReactive State\n====\n\nA typed, wrist-friendly state container aimed as an alternative to Redux when using RxJS. Written with RxJS in TypeScript but perfectly usable from plain JavaScript. Originally inspired by the blog posting from [Michael Zalecki](http://michalzalecki.com/use-rxjs-with-react/) but heavily modified and extended since.\n\nFeatures\n----\n\n  * type-safe actions: no boilerplate code, no mandatory string constants, and not a single switch statement\n  * Actions are just Observables, so are Subjects. Just call `.next()` to dispatch an action.\n  * dynamically add and remove reducers during runtime\n  * no need for async middlewares such as redux-thunk/redux-saga; actions are Observables and can be composed and transformed async using RxJS operators\n  * no need for selector libraries like MobX or Reselect, RxJS already ships it\n  * single, application-wide Store concept as in Redux. Possibility to create slices/substates for decoupling (easier reducer composition and state separation by module)\n  * Strictly typed to find errors during compile time\n  * Heavily unit tested, 100+ tests for ~250 lines of code\n  * React bridge (like `react-redux`) included, though using React is not mandatory\n  * Support for React-Devtool Extension\n\nInstallation\n----\n```\nnpm install reactive-state\n```\n\nDocumentation\n----\n\n  * [Wiki](https://github.com/Dynalon/reactive-state/wiki)\n  * [Demo App with annotated source](https://github.com/Dynalon/reactive-state-react-example) (includes react bridge examples)\n\nAdditionally, there is a small [example.ts file](https://github.com/Dynalon/reactive-state/blob/master/src/example.ts) and see also see the included [unit tests](https://github.com/Dynalon/reactive-state/tree/master/test) as well.\n\n\nExample Usage\n----\n\n```typescript\nimport { Store } from \"reactive-state\";\nimport { Subject } from \"rxjs\";\nimport { take } from \"rxjs/operators\";\n\n// The state for our example app\ninterface AppState {\n    counter: number;\n}\n\nconst initialState: AppState = { counter: 0 }\n\nconst store = Store.create(initialState);\n\n// The .watch() function returns an Observable that emits the selected state change, so we can subscribe to it\nstore.watch().subscribe(newState =\u003e console.log(\"STATE:\", JSON.stringify(newState)));\n\n// the watch() observable always caches the last emitted state, so we will immediately print our inital state:\n// [CONSOLE.LOG]: STATE: {\"counter\":0}\n\n// use a RxJS Subjects as an action\nconst incrementAction = new Subject\u003cnumber\u003e();\n\n// A reducer is a function that takes a state and an optional payload, and returns a new state\nfunction incrementReducer(state, payload) {\n    return { ...state, counter: state.counter + payload };\n};\n\nstore.addReducer(incrementAction, incrementReducer);\n\n// lets dispatch some actions\n\nincrementAction.next(1);\n// [CONSOLE.LOG]: STATE: {\"counter\":1}\nincrementAction.next(1);\n// [CONSOLE.LOG]: STATE: {\"counter\":2}\n\n// async actions? No problem, no need for a \"middleware\", just use RxJS\ninterval(1000).pipe(take(3)).subscribe(() =\u003e incrementAction.next(1));\n// \u003cPAUSE 1sec\u003e\n// [CONSOLE.LOG]: STATE: {\"counter\":3}\n// \u003cPAUSE 1sec\u003e\n// [CONSOLE.LOG]: STATE: {\"counter\":4}\n// \u003cPAUSE 1sec\u003e\n// [CONSOLE.LOG]: STATE: {\"counter\":5}\n```\n\nLicense\n----\n\nMIT.\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDynalon%2Freactive-state","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FDynalon%2Freactive-state","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FDynalon%2Freactive-state/lists"}