tigress v0.0.34
Tigress
Overview
tigress is a state management library that takes advantage of the robust type information available in TypeScript. It maintains a root state store which should be some immutable data structure and allows for atomically reading and writing that state store and receiving reactive change notifications upon state changes. It facilitates the creation of reusable components by providing a robust machanisms for navigating tree-like data structures.
tigress also provides constructs for reactive state computations along with React integration to allow for reactive view changes. In addition, there is advanced support for using state containers in data validation scenarios that allows for attaching validation metadata at any point in the state tree as well as accessing the current DB value of data being updated.
tigress's change notifications are compatible with RxJS and the proposed ECMAScript Observable specification.
Ref's
State containers in tigress are called Ref
s. Ref
s come in read-only and read-write variants. All readonly variants take a simple RO
suffix (i.e. RefRO
). All Ref
s take a single type parameter
representing the type of state managed by the Ref
, ex: Ref<number>
. When we refer to the types
of Ref
's in TypeScript, the interface form (IRef
or IRefRO
) is usually used as the return
value for functions in TypeScript.
rootRef
To create a new Ref
use the rootRef
function passing in the initial state:
const myRef : IRef<number> = rootRef(0);
get
The most basic operation for using Ref
's is to get the current state using the get()
method.
console.log(myRef.get());
// 0
Dependency Tracking
Calling get in a reactive computation (either inside a reaction
or reactive
React component)
will automatically register the Ref
as a dependency of the computation. This means that whenenver
the Ref
updates the reactive computation will update. (To get the current state without
registering the Ref
as a reactive dependency, use getNonReactive
.)
Nullability
Because Ref
s are meant to work with tree-like data structures, given a type T
that is
non-null we can't know whether it is the child of some nullable parent. So get
always
returns T | null
. (There is a variant of get
called getResolved
for "resolved" Ref's
that returns a non-null value but this is an advanced topic).
swap
and reset
If we have a regular read-write Ref
, swap
and reset
are used to modify the state. swap
takes
an update function which takes the current state and returns the new state. reset
simply takes a
value to set as the new state. Both swap
and reset
return the new value of the state after the
operation. Because Ref
's could point to values in nested tree data structures,
swap
and reset
are not guaranteed to succeed and thus the return value is the only reliable
way to know what the actual value of the state is after attempting to mutate it.
Ex:
myRef.swap(cur => cur != null ? cur + 1 : cur);
console.log(myRef.get());
// 1
myRef.reset(3);
console.log(myRef.get());
// 3
Nullability
Because of the complexities in working with tree-like data structures, the update function
passed to swap
must take a nullable value and can return a nullable value regardless of what
the underlying type for the Ref
is. reset
will only take a type that corresponds to the
nullability of the underlying type. Both swap
and reset
may take a nullable value.
subscribe
The subscribe
method is used to listen to change notifications from any Ref
-like containers.
subscribe
takes an IObserver
parameter and returns an ISubscription
value. IObserver
and ISubscription
in tigress correspond almost exactly to the Observer
and Subscription
interfaces specified in https://github.com/tc39/proposal-observable, with the minor difference
that tigress's IObserver
allows all fields to be optional. This allows for listening to
changes simply by providing the next
parameters of IObserver
:
myRef.subscribe({next: x => console.log(x)});
Prop's and Child Ref's
tigress
allows for easy interaction with nested state trees via Props which are
typed representations of the properties of objcets. There
are two basic Prop interfaces: IProp
and IPropRO
and read-write and read-only
properties respectively. All Prop's have a getter method and a string name and
read-write Prop's also have a setter method.
Prop Basics
Anything conforming to the IProp
or IPropRO
can be used in Tigress. The
simplest way to create Prop's is to use the provider Prop
and PropRO
types.
Prop getters, setters and name's are described below.
getter
A Prop getter is a function taking a parent value and returning a child value. To deal cleanly with nested trees, getters must always accept a possibly null parent and can always return a nullable value regardless of the underlying nullability of this Prop.
setter
A Prop setter is a function taking a parent value and a new child value and return a new value for the parent. To deal cleanly with nested trees, setters must always accept a possibly null parent value and possibly null new child value and can always return a nullable value. Thus it is up to Prop implementations to properly handle or reject null values.
name
The Prop's name
is more than just a description
string name, it is used to navigate metadata trees and
thus must be carefully chosen. This is an advanced topic
which will be discussed later in more detail.
Ref child
and childRO
Prop's are used by Ref's in order to create "child" Ref's.
That is - Ref's that behave just like any other Ref, but point
to a child value in the state tree. Every IRef
has child
function which takes an IProp
and returns another read-write
IRef
pointing to the child. Every IRef
and IRefRO
have
a childRO
function which takes an IPropRO
and returns
a read-only IRefRO
pointing to the child.
Creating Prop's via code-generation
Prop's are not intended to be created by hand except in the most basic cases. Internally Anywhere generates Props for all of the types in its API backend using Template Haskell. A similar code generator code be created for Typescript types using the Typescript compiler API.
Reactions
TODO
Resolved Ref's
TODO
Metadata
TODO
Clean Copy Ref's
TODO
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
6 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago
7 years ago