All Projects → lacolaco → reactive-store

lacolaco / reactive-store

Licence: MIT License
A store implementation for state management with RxJS

Programming Languages

typescript
32286 projects
javascript
184084 projects - #8 most used programming language

Projects that are alternatives of or similar to reactive-store

Ayanami
🍭 A better way to react with state
Stars: ✭ 129 (+344.83%)
Mutual labels:  rxjs, state-management
vuse-rx
Vue 3 + rxjs = ❤
Stars: ✭ 52 (+79.31%)
Mutual labels:  rxjs, state-management
Reactive State
Redux-clone build with strict typing and RxJS down to its core. Wrist-friendly, no boilerplate or endless switch statements
Stars: ✭ 135 (+365.52%)
Mutual labels:  rxjs, state-management
Sigi
Well designed effect management framework for complex frontend app
Stars: ✭ 95 (+227.59%)
Mutual labels:  rxjs, state-management
space-state
Demo app for Subjecting State to Good Behavior
Stars: ✭ 46 (+58.62%)
Mutual labels:  rxjs, state-management
Store
Aurelia single state store based on RxJS
Stars: ✭ 103 (+255.17%)
Mutual labels:  rxjs, state-management
rxdeep
rxjs deep state management
Stars: ✭ 47 (+62.07%)
Mutual labels:  rxjs, state-management
Platform
Reactive libraries for Angular
Stars: ✭ 7,020 (+24106.9%)
Mutual labels:  rxjs, state-management
ngx-mobx
Mobx decorators for Angular Applications
Stars: ✭ 14 (-51.72%)
Mutual labels:  rxjs, state-management
mst-effect
💫 Designed to be used with MobX-State-Tree to create asynchronous actions using RxJS.
Stars: ✭ 19 (-34.48%)
Mutual labels:  rxjs, state-management
ngx-model-hacker-news-example
Example repository with Hacker News implementation using Angular, Angular Material & ngx-model
Stars: ✭ 27 (-6.9%)
Mutual labels:  rxjs, state-management
aurelia-hoc-store
An Aurelia application showing the use of higher order components and a single state approach.
Stars: ✭ 20 (-31.03%)
Mutual labels:  rxjs, state-management
Rxstate
Simple opinionated state management library based on RxJS
Stars: ✭ 46 (+58.62%)
Mutual labels:  rxjs, state-management
Bloc.js
A predictable state management library that helps implement the BLoC design pattern in JavaScript
Stars: ✭ 111 (+282.76%)
Mutual labels:  rxjs, state-management
Mini Rx Store
Lightweight Redux Store based on RxJS
Stars: ✭ 32 (+10.34%)
Mutual labels:  rxjs, state-management
Model
Angular Model - Simple state management with minimalist API, one way data flow, multiple model support and immutable data exposed as RxJS Observable.
Stars: ✭ 242 (+734.48%)
Mutual labels:  rxjs, state-management
Fluorine
[UNMAINTAINED] Reactive state and side effect management for React using a single stream of actions
Stars: ✭ 287 (+889.66%)
Mutual labels:  rxjs, state-management
Focal
Program user interfaces the FRP way.
Stars: ✭ 613 (+2013.79%)
Mutual labels:  rxjs, state-management
ng-effects
Reactivity system for Angular. https://ngfx.io
Stars: ✭ 46 (+58.62%)
Mutual labels:  rxjs, state-management
flow-state
UI state management with RxJS.
Stars: ✭ 33 (+13.79%)
Mutual labels:  rxjs, state-management

@lacolaco/reactive-store

Very simple store implementation for state management with RxJS.

https://yarn.pm/@lacolaco/reactive-store

@lacolaco/reactive-store Dev Token

CI

npm version

Install

$ yarn add rxjs @lacolaco/reactive-store

Concept

  • RxJS: Use the ecosystem
  • TypeScript: Type-safe state management
  • Simple: Easy to understand what the library does and doesn't

How to Use

Create a store: new Store({ initialValue })

import { Store } from '@lacolaco/reactive-store';

export interface CounterState {
  count: number;
}

export const initialValue: CounterState = {
  count: 0,
};

export const counterStore = new Store<CounterState>({ initialValue });

Use the store

Get the current value: .value: T

export const counterStore = new Store<CounterState>({ initialValue: 1 });

console.log(counterStore.value); // => 1

Observe value changes: .valueChanges: Observable<T>

.valueChange returns a raw observable of the store.

export const counterStore = new Store<CounterState>({ initialValue: 1 });

counterStore.valueChanges.subscribe(value => {
  console.log(value); // => 1
});

// You can use `pipe` and operators of RxJS.
const doubled$: Observable<number> = counterStore.valueChanges.pipe(map(value => value * 2));

Update the store: .update((value: T) => T): void

update takes a function which takes the current value and returns a new value.

export const counterStore = new Store<CounterState>({ initialValue: 1 });

counterStore.update(value => value + 1);

console.log(counterStore.value); // => 2

Observe scoped value: .select((value: T) => U): Observable<U>

select method is for mapping and memoize the scoped value. This is using internally it uses RxJS's map and distinctUntilChanged operators.

export const counterStore = new Store<CounterState>({
  initialValue: { count: 1 },
});

counterStore.valueChanges.subscribe(value => {
  console.log(value); // => { count: 1 }
});

const selected$: Observable<number> = counterStore.select(value => value.count);

selected$.subscribe(value => {
  console.log(value); // => 1
});

Listen update events: .storeUpdateChanges: Observable<StoreUpdateChange<T>>

A store dispatchs a change event every time updating the store. This is for debugging or integrating with other tools.

const counterStore = new Store<CounterState>({
  initialValue,
});

counterStore.storeUpdateChanges.subscribe(change => {
  console.log(`Previous Value`, change.previousValue);
  console.log(`Current Value`, change.currentValue);
  console.log(`Label`, change.label);
});

label is a string value you can pass to update as an option.

export const counterStore = new Store<CounterState>({ initialValue: 1 });

counterStore.update(value => value + 1, { label: 'increment' });

Reset the store: .reset(): void

reset the store with the initial value.

export const counterStore = new Store<CounterState>({ initialValue: 1 });

counterStore.reset();

Integration Example

Use with immer

immer is a library to work with immutable state in a more convenient way. You can use immer intuitively with Store#update.

import { Store } from '@lacolaco/reactive-store';
import produce from 'immer';

const store = new Store({
  initialValue: { count: 0 },
});

store.update(
  produce(draft => {
    draft.count = 5; // mutate draft directly
  }),
);

console.log(store.value); // => 5

Use in Angular

In Angular application, I recommend to creating new store with extending Store and provide it for Dependency Injection.

// state/counter.store.ts
import { Injectable } from '@angular/core';
import { Store } from '@lacolaco/reactive-store';

export interface CounterState {
  count: number;
}

export const initialValue: CounterState = {
  count: 0,
};

// Or you can use your NgModule's `providers` array to provide this service.
@Injectable({ providedIn: 'root' })
export class CounterStore extends Store<CounterState> {
  constructor() {
    super({ initialValue });
  }
}
// app.component.ts
@Component({
  selector: 'app-root',
  template: `
    <p>Counter: {{ count$ | async }}</p>
  `,
})
export class AppComponent implements OnInit {
  count$: Observable<number>;
  constructor(private counterStore: CounterStore) {
    this.count$ = this.counterStore.select(value => value.count);
  }

  incrementCount() {
    this.counterStore.update(
      value => ({
        ...value,
        count: value.count + 1,
      }),
      { label: 'increment' },
    );
  }
}

License

MIT

Author

Suguru Inatomi a.k.a. @lacolaco

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].