{"id":13781677,"url":"https://github.com/rintoj/statex","last_synced_at":"2025-04-21T22:33:20.394Z","repository":{"id":57370019,"uuid":"92137695","full_name":"rintoj/statex","owner":"rintoj","description":"StateX is a state management library for modern web applications with unidirectional data flow and immutable uni-state (just like redux)","archived":false,"fork":false,"pushed_at":"2018-04-20T07:39:10.000Z","size":1247,"stargazers_count":68,"open_issues_count":7,"forks_count":18,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-04-13T02:47:12.733Z","etag":null,"topics":[],"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/rintoj.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}},"created_at":"2017-05-23T06:31:13.000Z","updated_at":"2025-04-06T16:57:20.000Z","dependencies_parsed_at":"2022-08-29T11:02:06.275Z","dependency_job_id":null,"html_url":"https://github.com/rintoj/statex","commit_stats":null,"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rintoj%2Fstatex","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rintoj%2Fstatex/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rintoj%2Fstatex/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rintoj%2Fstatex/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rintoj","download_url":"https://codeload.github.com/rintoj/statex/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250145220,"owners_count":21382374,"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":[],"created_at":"2024-08-03T18:01:28.159Z","updated_at":"2025-04-21T22:33:15.384Z","avatar_url":"https://github.com/rintoj.png","language":"TypeScript","funding_links":[],"categories":["List"],"sub_categories":[],"readme":"\n# StateX\n\nStateX is a state management library for modern web applications with unidirectional data flow and immutable uni-state. StateX is a predictable state container just like REDUX. It helps you implement a unidirectional data flow (Flux architecture) in an easy and elegant way without much boilerplate code. The main objective is to provide an implementation that has minimal touch points, while providing all the benefits of Redux. StateX uses `rxjs` library at its heart, hence promises efficient data flow. StateX is inspired by [refluxjs](https://github.com/reflux/refluxjs) and [redux](http://redux.js.org/).\n\nTo enable seamless integration, StateX has specific APIs for [Angular (2 or above)](https://angular.io) and [React](https://facebook.github.io/react/).\n\n**Note: StateX was originally written for angular - [ angular-reflux ]( https://github.com/rintoj/angular-reflux ) and later modified for react - [react-reflux]( https://github.com/rintoj/react-reflux ). Both of these packages are now migrated to StateX**\n\n- [StateX](#statex)\n- [Architecture](#architecture)\n- [Install](#install)\n- [Usage](#usage)\n- [Examples](#examples)\n- [5 Simple Steps](#5-simple-steps)\n  * [1. Define State](#1-define-state)\n  * [2. Define Action](#2-define-action)\n    + [Using TypeScript](#using-typescript)\n    + [Using ES6](#using-es6)\n  * [3. Create Store \u0026 Bind Action](#3-create-store--bind-action)\n    + [Angular with Decorator (Recommended)](#angular-with-decorator-recommended)\n    + [Angular without Decorator](#angular-without-decorator)\n    + [React - TypeScript with Decorators (Recommended)](#react---typescript-with-decorators-recommended)\n    + [React - ES6 with Decorators](#react---es6-with-decorators)\n    + [React - ES6 without Decorators](#react---es6-without-decorators)\n  * [4. Dispatch Action](#4-dispatch-action)\n  * [5. Consume Data](#5-consume-data)\n    + [Angular with Decorator (Recommended)](#angular-with-decorator-recommended-1)\n    + [Angular without Decorator](#angular-without-decorator-1)\n    + [React - TypeScript \u0026 Decorators (Recommended)](#react---typescript--decorators-recommended)\n    + [React - ES6 \u0026 Decorators](#react---es6--decorators)\n    + [React - ES6 and without Decorator](#react---es6-and-without-decorator)\n- [Organizing Stores](#organizing-stores)\n  * [Angular](#angular)\n  * [React - TypeScript / ES6](#react---typescript--es6)\n- [Reducer Functions \u0026 Async Tasks](#reducer-functions--async-tasks)\n- [Initialize State \u0026 Enable HotLoad](#initialize-state--enable-hotload)\n  * [Angular](#angular-1)\n  * [React](#react)\n- [Immutable Application State](#immutable-application-state)\n- [Migrating](#migrating)\n  * [Migrating from angular-reflux](#migrating-from-angular-reflux)\n  * [Migrating from react-reflux](#migrating-from-react-reflux)\n- [About](#about)\n  * [Contributing](#contributing)\n  * [Author](#author)\n  * [Versions](#versions)\n  * [License](#license)\n\n# Architecture\n\nFlux is an architecture for unidirectional data flow. By forcing the data to flow in a single direction, Flux makes it easy to reason *how data-changes will affect the application* depending on what actions have been issued. The components themselves may only update  application-wide data by executing an action to avoid double maintenance nightmares.\n\n![Flow](./docs/img/uni-flow.png)\n\n* **STATE** - contains application wide data. Technically this is a single immutable JavaScript object containing every data that an application needs.\n\n* **STORES** - contain business logic - how an action should transform the application wide data represented by `STATE`\n\n* **VIEWS** - Views must react to the change in `STATE`. So an event is triggered when `STATE` changes, which `VIEWS` can consume to update itself with the new data.\n\n* **ACTIONS** - are dispatched whenever a view needs to change application state. The actions contain payload to help store complete the updates.\n\n# Install\n```\nnpm install statex --save\n```\n\n# Usage\n\nStateX works with any modern JavaScript framework, however there are minor differences to how it is implemented for each framework.\n\nThis guide includes instructions to integrate StateX with the following combinations of frameworks and features\n\n| Framework | Language         | Decorator |               |\n|-----------|------------------|-----------|---------------|\n| Angular   | TypeScript       | YES       | (Recommended) |\n| Angular   | TypeScript       | NO        |               |\n| React     | TypeScript       | YES       | (Recommended) |\n| React     | ES6              | YES       |               |\n| React     | ES6              | NO        |               |\n\n\u003e Use [@angular/cli](http://npmjs.com/package/@angular/cli) to get started with Angular\n\n\u003e Use [react-ts](https://github.com/rintoj/react-ts) to get started with React \u0026 TypeScript\n\n\u003e Use [create-react-app](https://www.npmjs.com/package/create-react-app) to get started with React \u0026 ES6\n\nor use one of the following examples\n\n# Examples\n\n* [Angular with TypeScript \u0026 Decorators - AOT Compatible](https://github.com/rintoj/statex/tree/master/examples/todo-ng-ts)\n* [Angular with TypeScript \u0026 without Decorators - AOT Compatible](https://github.com/rintoj/statex/tree/master/examples/todo-ng-wo-decorators)\n* [React with TypeScript \u0026 Decorators](https://github.com/rintoj/statex/tree/master/examples/todo-react-ts)\n* [React with ES6 \u0026 Decorators](https://github.com/rintoj/statex/tree/master/examples/todo-react-es6)\n* [React with ES6 \u0026 without Decorators](https://github.com/rintoj/statex/tree/master/examples/todo-react-es6-wo-decorators)\n\n# 5 Simple Steps\n\n## 1. Define State\nTo get the best out of TypeScript, declare an interface that defines the structure of the application-state. This is optional if you don't want to use TypeScript.\n\n```ts\nexport interface Todo {\n  id?: string\n  title?: string\n  completed?: boolean\n}\n\nexport type Filter = 'ALL' | 'ACTIVE' | 'COMPLETED'\n\nexport interface AppState {\n  todos?: Todo[]\n  filter?: Filter\n}\n```\n\n## 2. Define Action\n\nDefine actions as classes with the necessary arguments passed on to the constructor. This way we will benefit from the type checking; never again we will miss-spell an action, miss a required parameter or pass a wrong parameter. Remember to extend the action from `Action` class. This makes your action listenable and dispatch-able.\n\n### Using TypeScript\n\n```ts\nimport { Action } from 'statex';\n\nexport class AddTodoAction extends Action {\n  constructor(public todo: Todo) {\n    super()\n  }\n}\n```\n\n### Using ES6\n\n```ts\nimport { Action } from 'statex';\n\nexport class AddTodoAction extends Action {\n  constructor(todo) {\n    super()\n    this.todo = todo\n  }\n}\n```\n\n## 3. Create Store \u0026 Bind Action\n\nStores are the central part of a Flux architecture. While most of the logics for a store are same, some of the minor details vary from framework to framework.\n\n### Angular with Decorator (Recommended)\n\nUse `@action` decorator to bind a reducer function with an Action. The second parameter to the reducer function (`addTodo`) is an action (of type `AddTodoAction`); `@action` uses this information to bind the correct action. Also remember to extend this class from `Store`.\n\n```ts\nimport { Injectable } from '@angular/core'\nimport { action, Store } from 'statex/angular'\n\n@Injectable()\nexport class TodoStore extends Store {\n\n  @action()\n  addTodo(state: AppState, payload: AddTodoAction): AppState {\n    return { todos: state.todos.concat([payload.todo]) }\n  }\n}\n```\n\n### Angular without Decorator\n\n```ts\nimport { Injectable } from '@angular/core'\n\n@Injectable()\nexport class TodoStore {\n\n  constructor() {\n    new AddTodoAction(undefined).subscribe(this.addTodo, this)\n  }\n\n  addTodo(state: AppState, payload: AddTodoAction): AppState {\n    return { todos: state.todos.concat([payload.todo]) }\n  }\n}\n```\n\nThis store will be instantiated by Angular's dependency injection.\n\n### React - TypeScript with Decorators (Recommended)\n\nUse `@action` decorator to bind a reducer function with an Action. The second parameter to the reducer function (`addTodo`) is an action (of type `AddTodoAction`); `@action` uses this information to bind the correct action.\n\n```ts\nimport { AppState } from '../state';\nimport { AddTodoAction } from '../action';\nimport { action, store } from 'statex/react';\n\n@store()\nexport class TodoStore {\n\n  @action()\n  addTodo(state: AppState, payload: AddTodoAction): AppState {\n    return { todos: state.todos.concat([payload.todo]) }\n  }\n}\n```\n\nStores must bind each action with the reducer function at the startup and also must have a singleton instance. Both of these are taken care by `@store` decorator.\n\n### React - ES6 with Decorators\n\n```ts\nimport { AddTodoAction } from '../action';\nimport { action, store } from 'statex/react';\n\n@store()\nexport class TodoStore {\n\n  @action(AddTodoAction)\n  addTodo(state, payload) {\n    return { todos: state.todos.concat([payload.todo]) }\n  }\n}\n```\n\n`@action` takes an optional parameter - the action class. Always remember to add `@store()` to the class.\n\n### React - ES6 without Decorators\n\n```ts\nimport { AddTodoAction } from '../action';\n\nexport class TodoStore {\n\n  constructor() {\n    new AddTodoAction().subscribe(this.addTodo, this)\n  }\n\n  addTodo(state, payload) {\n    return { todos: state.todos.concat([payload.todo]) }\n  }\n}\n\nnew TodoStore()\n```\n\nRemember to instantiate the store at the end.\n\n## 4. Dispatch Action\n\nNo singleton dispatcher! Instead StateX lets every action act as dispatcher by itself. One less dependency to define, inject and maintain.\n\n```ts\nnew AddTodoAction({ id: 'sd2wde', title: 'Sample task' }).dispatch();\n```\n\n## 5. Consume Data\n\nUse `@data` decorator and a selector function (parameter to the decorator) to get updates from application state. The property gets updated only when the value returned by the selector function changes from previous state to the current state. Additionally, just like a map function, you could map the data to another value as you choose.\n\nWe may, at times need to derive additional properties from the data, sometimes using complex calculations. Therefore `@data` can be used with functions as well.\n\nSee framework specific implementation.\n\n### Angular with Decorator (Recommended)\n\nWhile creating an Angular component, remember to extend it from `DataObserver`. It is essential to instruct Angular Compiler to keep `ngOnInit` and `ngOnDestroy` life cycle events, which can only be achieved by implementing `OnInit` and `OnDestroy` interfaces. `DataObserver` is  responsible for subscribing to state stream when the component is created and for unsubscribing when the component is destroyed. The selector function must also be kept as external functions accessible to outside modules, therefore add `export` to every selector function.\n\n```ts\nimport { data, DataObserver } from 'statex/angular';\n\nexport const selectState = (state: AppState) =\u003e state\nexport const selectTodos = (state: AppState) =\u003e state.todos\nexport const computeHasTodos = (state: AppState) =\u003e state.todos \u0026\u0026 state.todos.length \u003e 0\n\n@Component({\n    ....\n})\nexport class TodoListComponent extends DataObserver {\n\n  @data(selectTodos)     // mapping a direct value from state\n  todos: Todo[];\n\n  @data(computeHasTodos) // mapping a different value from state\n  hasTodos: boolean;\n\n  @data(selectState)     // works with functions to allow complex calculations\n  todosDidChange(state: AppState) {\n    // you logic here\n  }\n\n}\n```\n\n### Angular without Decorator\n\nStateX can also be used without decorators as shown below, however this is not a recommended way. At most care must be taken to unsubscribe all the events on destroy.\n\n```ts\nimport { State } from 'statex'\nimport { Subscription } from 'rxjs/Subscription'\n\nexport const selectTodos = (state: AppState) =\u003e state.todos\nexport const selectFilter = (state: AppState) =\u003e state.filter\n\n@Component({\n  ...\n})\nexport class AppComponent implements OnInit, OnDestroy {\n\n  todos: Todo[]\n  filter: Filter\n  subscriptions: Subscription[] = []\n\n  ngOnInit() {\n    this.subscriptions.push(\n      State.select(selectTodos).subscribe(todos =\u003e this.todos = todos)\n    )\n    this.subscriptions.push(\n      State.select(selectFilter).subscribe(filter =\u003e this.filter = filter)\n    )\n  }\n\n  ngOnDestroy() {\n    this.subscriptions.forEach(subscription =\u003e subscription.unsubscribe())\n    this.subscriptions = []\n  }\n}\n```\n\n### React - TypeScript \u0026 Decorators (Recommended)\n\nCreate `Props` class, add properties decorated with `@data`, and finally inject the `Props` to the container using `@inject` decorator.\n\n```tsx\nimport * as React from 'react'\nimport { data, inject } from 'statex/react'\n\nclass Props {\n  @data((state: AppState) =\u003e state.todos)\n  todos: Todo[]\n\n  @data((state: AppState) =\u003e state.todos \u0026\u0026 state.todos.length \u003e 0)\n  hasTodos: boolean\n}\n\ninterface State { }\n\n@inject(Props)\nexport class TodoListComponent extends React.Component\u003cProps, State\u003e {\n\n  render() {\n    const todos = this.props.todos.map(\n      todo =\u003e \u003cli key={todo.id}\u003e{todo.text}\u003c/li\u003e\n    )\n    return \u003cdiv\u003e { this.props.hasTodos \u0026\u0026 \u003cul\u003e {todos} \u003c/ul\u003e } \u003c/div\u003e\n  }\n}\n```\n\n### React - ES6 \u0026 Decorators\n\nCreate `Props` class, add properties decorated with `@data`, and finally inject the `Props` to the container using `@inject` decorator.\n\n```tsx\nimport * as React from 'react'\nimport { inject } from 'statex/react'\n\n@inject({\n  todos: state =\u003e state.todos,\n  hasTodos: state =\u003e state.todos \u0026\u0026 state.todos.length \u003e 0\n})\nexport class TodoListComponent extends React.Component {\n\n  render() {\n    const todos = this.props.todos.map(\n      todo =\u003e \u003cli key={todo.id}\u003e{todo.text}\u003c/li\u003e\n    )\n    return \u003cdiv\u003e { this.props.hasTodos \u0026\u0026 \u003cul\u003e {todos} \u003c/ul\u003e } \u003c/div\u003e\n  }\n}\n```\n\n### React - ES6 and without Decorator\n\n```tsx\nimport React from 'react'\nimport { State } from 'statex';\n\nexport class TodoListComponent extends React.Component {\n\n  subscriptions = [];\n\n  constructor(props) {\n    super(props)\n    this.state = {\n      todos: [],\n      hasTodos: false\n    }\n  }\n\n  componentDidMount() {\n    this.subscriptions.push(\n      State.select(selectTodos).subscribe(todos =\u003e this.setState({ todos }))\n    )\n    this.subscriptions.push(\n      State.select(computeHasTodos).subscribe(hasTodos =\u003e this.setState({ hasTodos }))\n    )\n  }\n\n  componentWillUnmount() {\n    this.subscriptions.forEach(subscription =\u003e subscription.unsubscribe())\n    this.subscriptions = []\n  }\n\n  render() {\n    const todos = this.state.todos.map(\n      todo =\u003e \u003cli key={todo.id}\u003e{todo.text}\u003c/li\u003e\n    )\n    return \u003cdiv\u003e { this.state.hasTodos \u0026\u0026 \u003cul\u003e {todos} \u003c/ul\u003e } \u003c/div\u003e\n  }\n\n}\n```\n\n# Organizing Stores\n\n## Angular\n\n* Create `STORES` array and a class `Stores` (again injectable) to maintain stores.\n\n```ts\nimport { Injectable } from '@angular/core';\nimport { TodoStore } from './todo.store';\n\n@Injectable()\nexport class Stores {\n  constructor( private todoStore: TodoStore) { }\n}\n\nexport const STORES = [\n  Stores,\n  TodoStore\n];\n```\n\n\u003e When you create a new store remember to inject to the `Stores`'s constructor and add it to the `STORES` array.\n\n* Add `STORES` to the `providers` in `app.module.ts`.\n\n```ts\nimport { STORES } from './store/todo.store';\n\n@NgModule({\n  providers: [\n    ...STORES\n  ],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n```\n\n* And finally, inject `Stores` into your root component (`app.component.ts`)\n\n```ts\n@Component({\n  ....\n})\nexport class AppComponent {\n  constructor(private stores: Stores) { }\n}\n```\n\n## React - TypeScript / ES6\n\nCreate `index.ts` in `stores` folder and import all stores. You must do this every store you create.\n\n```ts\nimport './todo-store'\n```\n\nImport stores into application (`app.tsx`), so that application is aware of the stores. This has to be done once at the beginning of the setup. Next time you create a new store, it must only be added to `store/index.ts`\n\n```ts\nimport './stores'\n...\nexport class AppComponent extends React.Component\u003c{}, {}\u003e {\n  ...\n}\n```\n\n# Reducer Functions \u0026 Async Tasks\n\nReducer functions can return either of the following\n\n* A portion of the application state as plain object\n\n```ts\n@action()\nadd(state: AppState, payload: AddTodoAction): AppState {\n  return {\n    todos: (state.todos || []).concat(payload.todo)\n  }\n}\n```\n\n* A port of the application state using async and await (RECOMMENDED)\n```ts\n@action()\nasync add(state: AppState, payload: AddTodoAction): Promise\u003cAppState\u003e {\n  const response = await asyncTask();\n  return (currentState: AppState) =\u003e ({\n    todos: (currentState.todos || []).concat(response.todo)\n  })\n}\n```\n\n\u003e Please note: the state might change by the time the `asyncTask()` is completed. So it is recommended to return a function that will receive the current state as shown above. Do all calculations based on `currentState` instead of `state`\n\n* A portion of the application state wrapped in Promise, if it needs to perform an async task.\n```ts\n@action()\nadd(state: AppState, payload: AddTodoAction): Promise\u003cAppState\u003e {\n  return new Promise((resolve, reject) =\u003e {\n    asyncTask().then(() =\u003e {\n      resolve((currentState: AppState) =\u003e ({\n        todos: (currentState.todos || []).concat(payload.todo)\n      }))\n    })\n  })\n}\n```\n\n* A portion of the application state wrapped in Observables, if the application state needs update multiple times over a period of time, all when handling an action. For example, you have to show loader before starting the process, and hide loader after you have done processing, you may use this.\n\n```ts\nimport { Observable } from 'rxjs/Observable'\nimport { Observer } from 'rxjs/Observer'\n\n@action()\nadd(state: AppState, payload: AddTodoAction): Observable\u003cAppState\u003e {\n  return Observable.create((observer: Observer\u003cAppState\u003e) =\u003e {\n    observer.next({ showLoader: true })\n    asyncTask().then(() =\u003e {\n      observer.next((currentState: AppState) =\u003e ({\n        todos: (currentState.todos || []).concat(payload.todo),\n        showLoader: false\n      }))\n      observer.complete()\n    })\n  })\n}\n```\n\n# Initialize State \u0026 Enable HotLoad\n\nYou can initialize the app state using the following code.\n\n```ts\nimport { initialize } from 'statex'\n\ninitialize(INITIAL_STATE, {\n\n  // set hot load to true to save and resume state between reloads\n  hotLoad: process.env.NODE_ENV !== 'production',\n\n  // show reducer errors; turn this off for production builds for performance reasons\n  showError: process.env.NODE_ENV !== 'production',\n  \n  // (electron only option) see electron section for details \n  cache: '.my-app-cache.json'\n  \n  // set this to uniquely identify your app in a common domain; in effect only if \"cache\" is not defined\"\n  domain: 'my-app'\n})\n```\n\nIf you set `hotLoad` to true, every change to the state is preserved in localStorage and re-initialized upon refresh. If a state exists in localStorage `INITIAL_STATE` will be ignored. This is useful for development builds because developers can return to the same screen after every refresh. Remember that the screens must react to state (reactive UI) in-order to achieve this. `domain` is an optional string to uniquely identify your application. `showError`, if set to true, displays console errors when the actions are rejected.\n\n\n## Angular\n\n```ts\n...\nimport { INITIAL_STATE } from './../state'\nimport { environment } from '../environments/environment'\nimport { initialize } from 'statex/angular'\n\ninitialize(INITIAL_STATE, {\n  hotLoad: !environment.production,\n  showErro: !environment.production,\n  domain: 'my-app'\n})\n\n@NgModule({\n  ....\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\n```\n\n## React\n\n```ts\n...\nimport { INITIAL_STATE } from './../state'\nimport { initialize } from 'statex/react'\n\ninitialize(INITIAL_STATE, {\n  hotLoad: process.env.NODE_ENV !== 'production',\n  showError: process.env.NODE_ENV !== 'production',\n  domain: 'my-app'\n})\n\nimport { AppComponent } from './app'\nReactDOM.render(\u003cAppComponent /\u003e, document.getElementById('root'))\n```\n\n## Electron\n\nIf you are building an electron app (using Angular or React), you can overcome the size limitation of localStorage using `cache` option. Set this property to a valid file name so that Statex will save the state in a local file instead of local storage. Remember to import `initialize` function from `statex/electron`.\n\n```ts\n...\nimport * as os from 'os'\nimport { INITIAL_STATE } from './../state'\nimport { initialize } from 'statex/electron'\n\ninitialize(INITIAL_STATE, {\n  hotLoad: process.env.NODE_ENV !== 'production',\n  showError: process.env.NODE_ENV !== 'production',\n  cache: path.resolve(os.tmpdir(), 'my-app-cache.json')\n})\n```\n\n# Immutable Application State\nTo take best use of React's and Angular's change detection strategies we need to ensure that the state is indeed immutable. This module uses [seamless-immutable](https://github.com/rtfeldman/seamless-immutable) for immutability.\n\nSince application state is immutable, the reducer functions will not be able to update state directly; any attempt to update the state will result in error. Therefore a reducer function should either return a portion of the state that needs change (recommended) or a new application state wrapped in `ReplaceableState`, instead.\n\n```ts\n@action()\nselectTodo(state: AppState, payload: SelectTodoAction): AppState {\n  // merge with the existing state\n  return {\n    selectedTodo: payload.todo\n  }\n}\n\n@action()\nresetTodos(state: AppState, payload: ResetTodosAction): AppState {\n  // replace the current state completely with the new one\n  return new ReplaceableState({\n    todos: [],\n    selectedTodo: undefined\n  })\n}\n```\n\n# Migrating\n\n## Migrating from angular-reflux\n\n* Replace `angular-reflux` package with `statex`\n\n```bash\nnpm uninstall react-reflux --save\nnpm install statex --save\n```\n* Replace imports from `angular-reflux` to `statex/angular`\n\n```ts\n// from\nimport { data, DataObserver } from 'angular-reflux'\n\n// to\nimport { data, DataObserver } from 'statex/angular'\n```\n\n* Change `@BindAction()` to `@action()`\n\n```ts\n// from\n@BindAction()\naddTodo(state: AppState, action: AddTodoAction): AppState {\n  ...\n}\n\n// to\n@action()\naddTodo(state: AppState, action: AddTodoAction): AppState {\n  ...\n}\n```\n\n* Change `@BindData()` to `@data()`\n```ts\n// from\n@Component({...})\nexport class AppComponent extends DataObserver {\n  @BindData(selectTodos)\n  todos: Todo[]\n}\n\n// to\n@Component({...})\nexport class AppComponent extends DataObserver {\n  @data(selectTodos)\n  todos: Todo[]\n}\n```\n\n## Migrating from react-reflux\n\nTo migrate to StateX replace the package `react-reflux` with `statex`.\n\n```bash\nnpm uninstall react-reflux --save\nnpm install statex --save\n```\n\nAnd change every import statement from `react-reflux` to `statex/react`. That's all\n\n```ts\n// from\nimport { data, inject } from 'react-reflux'\n\n// to\nimport { data, inject } from 'statex/react'\n```\n# About\n\n### Hope StateX is helpful to you. Please make sure to checkout my other [projects](https://github.com/rintoj) and [articles](https://medium.com/@rintoj). Enjoy coding!\n\n## Contributing\nContributions are very welcome! Just send a pull request. Feel free to contact [me](mailto:rintoj@gmail.com) or checkout my [GitHub](https://github.com/rintoj) page.\n\n## Author\n\n**Rinto Jose** (rintoj)\n\nFollow me:\n  [GitHub](https://github.com/rintoj)\n| [Facebook](https://www.facebook.com/rinto.jose)\n| [Twitter](https://twitter.com/rintoj)\n| [Google+](https://plus.google.com/+RintoJoseMankudy)\n| [Youtube](https://youtube.com/+RintoJoseMankudy)\n\n## Versions\n[Check CHANGELOG](https://github.com/rintoj/statex/blob/master/CHANGELOG.md)\n\n## License\n```\nThe MIT License (MIT)\n\nCopyright (c) 2017 Rinto Jose (rintoj)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frintoj%2Fstatex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frintoj%2Fstatex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frintoj%2Fstatex/lists"}