Quick Start
Install
npm i staterx rxjs
or
yarn add staterx rxjs
Counter Example
import { createValue } from 'staterx';// create a counter// counter holds a value and a basic api// get, set, reset, and state$const counter = createValue({default: 0});console.log(counter.get()); // logs 0counter.set(1); // update the valueconsole.log(counter.get()); // logs 1
In the most basic example, we have a single value that we are creating and updating imperatively. RxJS natives are probably thinking "isn't this just a Behavior Subject?" Obviously in this contrived example, it's not obvious that we have any benefit over using a regular variable.
The real power of this example is that we actualy just created a stateful stream we can hook into by using RxJS as well as an idiomatic api for basic functionality like getting and setting. We can also specify effects
to indicate how we want this variable to change over time.
Effects
Noun: a change which is a result or consequence of an action or other cause.
Verb: cause (something) to happen; bring about.
One of this inspirations for this library was an article (that I can no longer find to link to...) that talked about how state management in JS has gotten out of control over the years. After years of doing Redux we've ended up with Stores, Dispatchers, Actions, Selectors, Thunks, Epics, Sagas, Side Effects, and Actors. For StateRx, these concepts are just called "effects".
Effects allow us to specify how we want to change one of our stateful values, and also how we would like to read them through computed changes. If you're coming from Redux, you might have heard them referred to as "actions" and "selectors".
Lets update our example to be a bit more useful and include some effects.
import { createValue } from 'staterx';import { scan } from 'rxjs/operators';const counter = createValue({default: 0,effects: ({ state$ }) => ({// here we create two functions that describe how we want to change our valueincrement: () => counter.set(val => val + 1),decrement: () => counter.set(val => val - 1),// an observable to count of the total number of times our counter has changedcallCount$: state$.pipe(scan(acc => acc + 1, -1))// an example of an async effectsave: async () => {const myVal = counter.get();await fetch('/example/save/', {...}); // do something async}})});counter.state$.subscribe(val => console.log(val)); // logs 0counter.increment(); // logs 1counter.decrement(); // logs 0// we can also subscribe to our callCount$ effectcounter.callCount$.subscribe(val => console.log(val));
React Example
StateRx ships with a hooks for React so you can directly consume your state in your components. Just import useRx
and pass your variable's state$ to the hook. useRx
actually works with more than just StateRx, you can pass any RxJS Observable.
import { createValue, useRx } from 'staterx';
- Count: 0
- Num Calls: