1.0.5 • Published 2 years ago

rxjs-lib v1.0.5

Weekly downloads
-
License
MIT
Repository
-
Last release
2 years ago

semantic-release semantic-release CircleCI

RXJS Util

Fully inspired by Mark E's @rx-utils

State management utilities based on RxJS

This library provides a very thin wrapper around some RxJS objects that are useful for state management.

There are only two main components: atom and combine.

Install

// Via NPM
$ npm install --save rxjs-lib

// Via Yarn
$ yarn add rxjs-lib

Usage

atom

This is very simply a container for any value that changes. It's a thin wrapper around an RxJS BehaviorSubject.

You simply wrap a static value with atom

import { atom } from "rxjs-lib";
const word$ = atom("Hello");

The $ at the end is a convention sometimes used to indicate an observable object.

Now you can subscribe to updates with a callback

const sub = word$.subscribe((word) => console.log(`Word is now ${word}`));
// Logs "Word is now Hello"

Set a new value

word$.set("Hello World");
// Logs "Word is now Hello World"

To avoid memory leaks you should unsubscribe when finished

sub.unsubscribe();

The atom function returns a WritableAtom, which has the following methods:

const $word = atom("Hello");

$word.get()                            // "Hello"
$word.set("Hey")                       // sets value to "Hey" and notifies subscribers
$word.update(n => n + " World")       // set to "Hello World" -
                                       //   use instead of set if you want to use the previous value

const uppercaseWord$ = $word.pipe(     // pipe can be used as per usual in RxJS,
  map(n => n.toUpperCase()),           // and returns an RxJS observable
  ...
)
const lowercaseWord$ = $word.map(n => n.toLowerCase()) // "map" is provided for convenience so you
                                                       //   don't need pipe, and returns a ReadonlyAtom

const $wordRO = $word.readonly()       // returns a read-only version of the atom (ReadonlyAtom)
$wordRO.get()    // "Hello World"
$wordRO.set(...) // ERROR - METHOD DOESN'T EXIST!

$word.destroy()                        // rarely used but can use to remove all subscribers

The ReadonlyAtom is similar but only has get, map, pipe and subscribe.

readonlyAtom

This is a convenience method for creating a read-only atom, that also yields a setter function.

const [count$, setCount] = readonlyAtom(4);
count$.get(); // 4 - this is just a ReadonlyAtom

setCount(7);
count$.get(); // 7

This would be useful for e.g. using in a class, where the read-only atom is public, but the setter is private:

class Person {
  public name$: ReadonlyAtom<string>;
  private setName: (name: string) => void;

  constructor(initialName: string) {
    [this.name$, this.setName] = readonlyAtom(initialName); // NOTE the parentheses when doing this
  }

  //... use this.setName("...") internally
}

const person = new Person("Fred");
person.name$.set("Bubba"); // ERROR: name$ is readonly so has no 'set'

combine

This combines RxJS observables or atoms in a way that is useful for efficiently using derived values.

Given multiple atoms (or other synchronous RxJS observables)

const names$ = atom(["Geoffrey", "Bungle", "George", "Zippy"]);
const selectedIndex$ = atom(1);

Then you can combine them into a new observable with a tuple

const selectedName$ = combine(
  [names$, selectedIndex$], // tuple of multiple observables
  ([names, index]) => names[index] // calculate new value derived from values from observables
);
selectedName$.get(); // "Bungle"

or with an object

const selectedName$ = combine(
  { names: names$, idx: selectedIndex$ }, // object lookup of multiple observables
  ({ names, idx }) => names[idx] // calculate derived value
);
selectedName$.get(); // "Bungle"

The new observable is efficient in that

  • it only makes the calculation (the 2nd argument function) once when any of its input observables have changed
  • it doesn't make the calculation if no-one is subscribing

In both forms you can also call combine with no 2nd argument

const selectedName$ = combine({ names: names$, idx: selectedIndex$ }); // = an observable that emits {names: string[], idx: number} objects

const selectedName$ = combine([names$, selectedIndex$]); // = an observable that emits [string[], number] objects

get

This library provides a convenience method for synchronously getting the value from an RxJS observable

get(count$); // 7

This only works in cases where it's able to give its current value synchronously either because

  • it calls subscription callbacks synchronously, or
  • it's a BehaviorSubject

Otherwise it will throw an error

const click$ = fromEvent(document, "click");
get(click$); // THROWS AN ERROR -
//   it doesn't make sense here as click$ is asynchronous

Semantic release

Release management is automated using semantic-release.

License

The MIT License

1.0.5

2 years ago

1.0.4

2 years ago

1.0.3

2 years ago

1.0.2

2 years ago

1.0.1

2 years ago

1.0.0

2 years ago

0.0.1

2 years ago