# Introduction

![](https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-ML-_x6pGjjn-ywf-yR-%2F-ML0SMhBvx_M9VHYM-iq%2FAJS%20Logo%20Full%20-%20Padded.png?alt=media\&token=5875624c-9eea-46f6-80d1-5487906806f7)

ActiveJS strives to be a pragmatic, reactive state management solution for JavaScript apps.

ActiveJS' reactivity is based on [RxJS Observable](https://rxjs.dev/guide/observable), hence, you can take full advantage of [RxJS operators](https://rxjs.dev/guide/operators).

It's built around **reactive data structures** called [**Units**](/activejs/fundamentals/units) that resemble JavaScript's **native data structures** but are much more powerful.  All these feature-packed reactive data structures share the following qualities:&#x20;

* Observable value
* Reactive value mutation
* Type-safety
* Cache-enabled
* Optionally Immutable&#x20;
* Optionally Persistent

These Units help you share data among different parts of an app with minimum code and effort.\
Furthermore, ActiveJS helps in streamlining asynchronous data APIs like `XHR`, `fetch`, or third party abstractions like Angular's `HttpClient` or `axios`, etc.

## Installation

If you don't have [RxJS](https://rxjs.dev/guide/installation) installed already, you'll need to install it first `npm install rxjs`, and then

```bash
npm i @activejs/core
```

## Quick Example

This is how an implementation of a simple "counter" looks like, using a [NumUnit](/activejs/fundamentals/units/numunit), one of the reactive data structures that ActiveJS provides. The [NumUnit](/activejs/fundamentals/units/numunit) stores and provides a `number` value at all times ensuring the **type-safety**.

```typescript
// initialize a reactive data structure to store numbers
const counter = new NumUnit() // with default initial-value 0

// two pure functions to produce an appropriate new value
const increment = value => value + 1 
const decrement = value => value - 1

// subscribe for reactive value access, and log the value
counter.subscribe(value => console.log(value))
// immediately logs 0, and will log any future values

// increment
counter.dispatch(increment); // you'll see 1 in the console
// the pure function is called with the current value and
// the returned value is dispatched automatically

// decrement
counter.dispatch(decrement); // you'll see 0 in the console
// that's it our counter is complete

// you can also access the value directly
console.log(counter.value()) // logs 0
```

You never have to worry if the value of this **counter** is `number` or not, the [NumUnit](/activejs/fundamentals/units/numunit) will ensure that it's a `number`, it'll ignore any non-`number` value dispatch. We'll talk about it in detail later.

## Quick Comparisons

A "counter" implemented in vanilla **Redux** vs **ActiveJS**. \
It's not a fair comparison because a [NumUnit](/activejs/fundamentals/units/numunit) can do so much more alone, and Redux is powerful in its own way. But it is what it is.

![Redux vs ActiveJS](https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-MJv31iWOnLCO37G0TJF%2F-MJvF07bHgk9u6k3NSQc%2FRedux%20vs%20ActiveJS.png?alt=media\&token=c381d6e2-59a9-4bd9-9ed5-09ba75028920)

It's hard to  Compare with **NgRx** without involving Angular, but for argument's sake let's pretend that this stripped-down code is valid.

![NgRx vs ActiveJS](https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-MJv31iWOnLCO37G0TJF%2F-MJvF5zhSD-B6xt0SVmo%2FNgRx%20vs%20ActiveJS.png?alt=media\&token=3bafc003-6bb8-4515-b6be-7113f6fd89ce)

## Quick Overview

The following data-flow diagram roughly shows where ActiveJS comes into play.\
ActiveJS holds the state and every other part of the application directly shares it without any obscure façade.

![A very high level data-flow diagram of an App using ActiveJS.](https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-MAsFH3yDU9S0O2wrt5E%2F-MAurwB-A0FWl-CvM3rN%2FVery%20High%20Level%20Data%20Flow%20\(1\).svg?alt=media\&token=b89c5e63-33d9-41c5-9873-371ede39ac76)

ActiveJS is fully [fuzz-tested](https://en.wikipedia.org/wiki/Fuzzing) with **99.99%** code-coverage.

ActiveJS is really small in size, and it's **tree-shakeable** too.\
Also, there're **no reducers, no middleware, and not even a store for that matter**.\
It's much simpler than that.&#x20;


# Getting Started

## Installation

If you don't have [RxJS](https://rxjs.dev/guide/installation) already, you'll need to install it first `npm install rxjs`, and then

```bash
npm i @activejs/core
```

If you don't have access to a module bundler, here's the [UMD bundle link](https://unpkg.com/@activejs/core/bundles/activejs-core.umd.min.js). (not needed for frameworks like Angular, React, Vue etc.)

## Prerequisite

ActiveJS assumes a prior understanding of [Observables](https://rxjs-dev.firebaseapp.com/guide/observable). Some understanding of RxJS can also be helpful, but the basic knowledge of Observables should be enough. [This official guide](https://rxjs-dev.firebaseapp.com/guide/observable) or [this primer](https://www.learnrxjs.io/learn-rxjs/concepts/rxjs-primer) might help you get up to speed.

## Prelude

Imagine a variable that can only be assigned a value of a particular data type, let's say only `number`, and when we change the value of this variable, it gets broadcasted to observers, while we also keep past values in the cache to be able to undo/redo. That's basically what an ActiveJS [Unit](/activejs/fundamentals/units) allows us to do, and the one that only allows numbers is called [NumUnit](/activejs/fundamentals/units/numunit).

At the heart of ActiveJS are these reactive data structures called[ Units](/activejs/fundamentals/units), that emulate JavaScript's native data structures. Units behave **almost** exactly like a native data structure would, while the actual value is kept encapsulated inside the Unit. Units are observable and every operation and mutation is broadcasted.

#### Quick Example:

Let's take a simple and comparable example of implementing a counter.\
We'd use a [NumUnit](/activejs/fundamentals/units/numunit) for the counter since we expect the value to always be a `number`.

```typescript
// initialize a NumUnit.
const counterUnit = new NumUnit({initialValue: 6});
// NumUnit has default initial value 0,
// you can also provide an initial value.
```

```typescript
// observe the Unit for current and future values
counterUnit.subscribe(value => console.log(value)) 
// logs 6 immediately and will log future values

// or, directly access the current value
console.log(counterUnit.value()); // logs 6
```

```typescript
// define two pure functions that produce a new value
const increment = value => value + 1; 
const decrement = value => value - 1;

// now we'll use the above pure functions as value-producers,
// the dispatch method expects a value or a value-producer-function
counterUnit.dispatch(increment); // makes the value 7
counterUnit.dispatch(decrement); // makes the value 6 again

// or just directly pass the value
counterUnit.dispatch(7); // makes the value 7

// try an invalid value
counterUnit.dispatch('20'); // NumUnit will ignore this invalid string value
// so the value is still 7
```

Try it on [StackBlitz](https://stackblitz.com/edit/rxjs-daesrs?file=index.ts).\
Or, let's also try some built-in methods.

{% hint style="info" %}
ActiveJS Units are cache-enabled, and by default, every Unit caches two values.\
When you navigate through the cache, the cache stays intact, while the value changes.\
This makes it very easy to travel back in time and then go back to the future.
{% endhint %}

```typescript
// to recap, the list of cached values is [6, 7] at the moment
// and the current value is 7

// go back to the previous value
counterUnit.goBack(); // now value is 6 (cache isn't affected)

// go forward to the next value
counterUnit.goForward(); // now value is 7 (cache isn't affected)

// clear the value
counterUnit.clearValue(); // now value is 0 (the default value for NumUnit)

// reset the value
counterUnit.resetValue(); // now value is 6 again (the initial-value)
```

There are even more built-in things that a Unit can do, but this is the crux of it.

## Fundamentals

Other constructs within ActiveJS build on the core concept of independent storage Units and work together to create a complete workflow for advanced use cases.

ActiveJS is made up of four fundamental constructs, visualized with their core components in the diagram below. Each one of them plays a different yet crucial role in the complete state-management lifecycle.

![Bird's eye view of ActiveJS constructs.](https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-M8__cvBusEu6yFJke55%2F-M8eij5iyf0NAVnLbCxt%2FActiveJS%20Constructs.svg?alt=media\&token=008059c7-0537-4eb0-bc05-b401f59a06f2)

* [**Units**](/activejs/fundamentals/units) are independent, reactive data structures. Units are responsible for holding the state of your App.&#x20;
  * Units are cache-enabled, and based on JavaScript's native data structures like `boolean`, `string` or `array`.
  * For example, [ListUnit](/activejs/fundamentals/units/listunit) is an elaborate `array` like construct which is also an Observable and implements all the `Array.prototype` methods in a way that, any mutation caused by these methods, emits a new `array` with the mutations applied to it.
  * All available Units are [BoolUnit](/activejs/fundamentals/units/boolunit), [NumUnit](/activejs/fundamentals/units/numunit), [StringUnit](/activejs/fundamentals/units/stringunit), [ListUnit](/activejs/fundamentals/units/listunit), [DictUnit](/activejs/fundamentals/units/dictunit), and [GenericUnit](/activejs/fundamentals/units/genericunit).<br>
* [**Systems**](/activejs/fundamentals/systems) encompass a certain number of [Units](/activejs/fundamentals/units) in a specialized way and implement inter-relationships among these Units to pertain to a specific task. For now, there's only one of its kind.
  * [**AsyncSystem**](/activejs/fundamentals/systems/asyncsystem) helps with async APIs like `XHR` or `fetch`, it makes sharing their state very easy.<br>
* [**Actions**](/activejs/fundamentals/action) are meant to represent unique events as `Observables`. Action is an RxJS `Subject` like construct, with extra features like replay on demand. Actions are useful, but not essential to start using ActiveJS.<br>
* [**Cluster**](/activejs/fundamentals/cluster) is literally a cluster, a wrapper, that can be used to create a group of [Units](/activejs/fundamentals/units), [Systems](/activejs/fundamentals/systems), [Actions](/activejs/fundamentals/action) as well as [Clusters](/activejs/fundamentals/cluster). It creates a master `Observable` of the combined value of its members, and also provides direct static access to the combined value.

## [Playground](http://activejs.github.io/)

To jump right into the action without writing any code, you can try out [this visual playground](https://activejs.dev/#/playground), it might give you some more perspective, and help understand the most important ActiveJS constructs [Units](/activejs/fundamentals/units), and [Systems](/activejs/fundamentals/systems).

## Do I need ActiveJS?

As much as we'd like to say YES, we don't want you to get into something that you later realize is not for you.

That being said,\
If you're coming from a Flux background you'll see that it's different yet somehow familiar and easier.\
If you feel like Flux based state management solutions are overkill, you'll love it.\
If you're happy with RxJS, you'll be able to do more by doing less.\
If your single-page app is not using Observables, it can give you wings (maybe).

So, do you need it? The answer is we are not sure, it can definitely help you in one way or another, you can start small without much commitment, give it a go and see how it pans out.


# Key Characteristics

ActiveJS has many unique and many not so unique qualities, but each quality is cherry-picked and serves a well thought out purpose. Probably the strongest point of ActiveJS is that all these qualities come in a single package, which serves our goal of reducing the complexity by reducing the number of moving parts.

*(in no particular order)*\
ActiveJS is:

### Intuitive

ActiveJS tries to not drift too far away from vanilla JavaScript and re-employs many well-established concepts, albeit in a slightly different way. We believe this enhances the developer experience and makes our lives a little bit easier.

### Reactive

Every fundamental ActiveJS construct is an Observable and every built-in operation has a dedicated Observable event. In order to achieve full reactivity, every operation has a reaction, even if it's not equal.

### Proactive

Instead of relying on implicit and sometimes confusing data-processing (i.e. **reducers**), ActiveJS promotes proactive processing of data using **value-producers**, so that you can write functional, easily testable code, without breaking the flow of code.

### Less verbose

Less code isn't always a good thing, but neither is more code. We're firm believers in the *"no code, no bugs"* philosophy.\
ActiveJS is not necessarily the least verbose, but we built ActiveJS keeping verbosity in mind, and it was also one of the motivations behind building it.

### Less obscure

We believe having independent storage [Units](/activejs/fundamentals/units) helps reduce a lot of façades, which is otherwise essential for single store solutions. This allows us to keep the number of abstract utility concepts needed at a minimum. Also, we deliberately keep the abstraction at a minimum to avoid any unnecessary confusion.

### Strongly-typed

ActiveJS is developed in TypeScript and it's strongly-typed, which brings all the benefits of a robust typings system, faster development, and fewer surprises to say the least.

### Cache-enabled

Units can cache up to Infinite number of values, which makes operations like replay, undo, redo, or jumping to a specific point in the cache very easy; in other words *TiMe-TrAvEL* is possible. Other constructs like Cluster, Action, and AsyncSystem also cache one value, so you can replay it on demand.

### Immutable

Units are responsible for holding the state, and making these Units immutable is as easy as setting a configuration flag. Units implement immutability in such a way that it doesn't become a bottleneck.

### Persistent

Making a Unit persist it's value in the LocalStorage or SessionStorage is as easy as setting a configuration flag. Since the Units are independent, making a Unit persistent is very performant and efficient.

### Efficient

Units only allow allocated type of value to get through, which avoids the need for many validity and sanity checks. All Units also have the built-in capability to ignore duplicate values, to avoid unnecessary overhead. There's no single store, independent Units hold the state, and changing the value of a Unit doesn't trigger change detection all over the place.

### Configurable

ActiveJS gives you the opportunity to configure it in your own way. Although it's already configured with sensible defaults, the options are there so that you can fine-tune it according to the task at hand.

These are the most prominent characteristics of ActiveJS, but they won't amount to anything if the DX is not enhanced, because that's the end goal of ActiveJS. Hence, the Developer Experience is of utmost importance, and every decision is made keeping DX in mind. That's what ActiveJS is all about, being pragmatic rather than idealistic.


# Fundamentals

ActiveJS has 4 fundamental types of constructs, [Units](/activejs/fundamentals/units), [Systems](/activejs/fundamentals/systems), [Action](/activejs/fundamentals/action), and [Cluster](/activejs/fundamentals/cluster). All these constructs are Observables since they extend RxJS' Observable class.

You don't need to learn all of them to start using ActiveJS; [Units](/activejs/fundamentals/units) and [Actions](/activejs/fundamentals/action) can be used independently without any further understanding of [Systems](/activejs/fundamentals/systems) or [Clusters](/activejs/fundamentals/cluster). Also, ActiveJS is *tree-shakeable,* hence the parts that you don't use, will not get bundled in your build.

This data-flow diagram might give you some perspective before we dive into details. It shows how ActiveJS is connected with other parts of a Web app. All parts of an App can communicate with any instance of an ActiveJS construct directly, there is no abstraction layer involved like a Store, Dispatcher, Middleware, or Reducer.

![](https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-MAsFH3yDU9S0O2wrt5E%2F-MAus4bPOAPnL1weZwja%2FHigh%20Level%20Data%20Flow%20\(1\).svg?alt=media\&token=e7494c6e-0ec8-434f-8746-1699109aec09)

### 1. [Units](/activejs/fundamentals/units)

* Every state management solution relies on a robust storage system, and for that exact purpose, ActiveJS has independent, reactive storage Units. Simply called **Units**.
* Units emulate JavaScript's native data structures. There's a specialized type of Unit for each of the most used native data structures. All the Units are also `Observables`.
  * [**BoolUnit**](/activejs/fundamentals/units/boolunit) is a `boolean` counterpart, it stores and provides a `boolean` value at all times.
  * [**NumUnit**](/activejs/fundamentals/units/numunit) is a `number` counterpart, it stores and provides a `number` value at all times.
  * [**StringUnit**](/activejs/fundamentals/units/stringunit) is a `string` counterpart, it stores and provides a `string` value at all times.
  * [**ListUnit**](/activejs/fundamentals/units/listunit) is an `array` counterpart, it stores and provides an `array` value at all times.
  * [**DictUnit**](/activejs/fundamentals/units/dictunit) is loosely based on `Map`, it stores and provides a simple `object` value at all times.
  * [**GenericUnit**](/activejs/fundamentals/units/genericunit) doesn't pertain to any specific data type, it's generic in nature, it can store any type of value.

```typescript
// initialize a Unit
const messageUnit = new StringUnit(); // StringUnit has default-value ''

// listen for the values
messageUnit.subscribe(value => console.log(value));
// logs '' immediately, and will log 'hello' after next step

// dispatch a new value
messageUnit.dispatch('hello'); // StringUnit only acccepts strings

// directly access value
console.log(messageUnit.value()); // logs 'hello'
```

### **2.** [**Systems**](/activejs/fundamentals/systems)

* Reactive storage Systems help with async APIs like **XHR** and **fetch** or any third party abstraction.
* A System is just a systematic combination of one or more [Units](/activejs/fundamentals/units) with pre-configured inter-relationships.
* For example, [AsyncSystem](/activejs/fundamentals/systems/asyncsystem) can be used to store, share, replay, and wait for async tasks. This is realized by utilizing **four** Units for every aspect of an async task, it includes **three** [GenericUnits](/activejs/intro/getting-started), one each for `query`, `response` and `error`, and **one** [BoolUnit](/activejs/fundamentals/units/boolunit) for the `pending-status` of an async task.

```typescript
// initialize a System for fetching and sharing user data
const userDataSystem = new AsyncSystem();

// extract the Units, that are part of the AsyncSystem
const {queryUnit, dataUnit, errorUnit, pendingUnit} = userDataSystem;
// using destructuring assignment

// a function to fetch data and disptch the response appropriately
async function fetchAndShareData(query) {
  try {
    // fetch data using fetch API
    const response = await fetch('https://xyz.com/u/' + query.userId);
    // extract the JSON data
    const data = await response.json();

    // dispatch data to the dataUnit, it also sets the pendingUnit's value to false
    // and it also clears the errorUnit's value
    dataUnit.dispatch(data);
  } catch (err) {
    // dispatch error to errorUnit, it also sets the pendingUnit's value to false
    errorUnit.dispatch(err);
  }
}

// setup the stream by observing query values, that triggers fetchAndShareData
// whenever a value is dispatched to queryUnit
queryUnit.subscribe(query => fetchAndShareData(query));
```

Our setup is complete, now we can easily share `query`, `data`, `error` and `pending-status` with different parts of our App.

```typescript
// listen for queries
queryUnit.subscribe(query => console.log(query));

// listen for data
dataUnit.subscribe(data => console.log(data));

// listen for errors
errorUnit.subscribe(error => console.log(error));

// listen for pending status
pendingUnit.subscribe(isPending => console.log(isPending));
```

Now, all we need to do is trigger a new API request, which also can be done from anywhere, like this:

```typescript
// dispatch a query, it'll also set pendingUnit's value to true
// the rest will be handled by the stream we just created above
queryUnit.dispatch({userId: 42069});
```

### **3.** [**Actions**](/activejs/fundamentals/action)

* Actions are meant to represent unique reactive events. Action is an RxJS [Subject](https://rxjs.dev/guide/subject) like construct, it also extends RxJS Observable, and implements custom features like replay on demand.
* Actions help trigger customized operations in a reactive fashion.

```typescript
// initialize an Action
const notifier = new Action();

// every time the Action emits, we alert
notifier.subscribe(message => alert(message));
// not executed on subscription, waits for a dispatch

// we can dispatch any value from anywhere
notifier.dispatch('Say Sike');

// replay the last value
notifier.replay(); // will emit 'Say Sike' again

// directly access value
console.log(notifier.value()); // logs 'Say Sike'
```

### **4.** [Clusters](/activejs/fundamentals/cluster)

* A Cluster is a wrapper of two or more [Units](/activejs/fundamentals/units), [Systems](/activejs/fundamentals/systems), [Actions](/activejs/fundamentals/action), or even [Clusters](/activejs/fundamentals/cluster). It's intended to be used to create a group of several ActiveJS instances.
* It creates a master Observable of combined values of provided members of the Cluster.
* It also provides direct access to its members and their combined value.

```typescript
// create a few Units to combine
const numUnit = new NumUnit(); // with default value 0
const strUnit = new StringUnit(); // with default value ''
const listUnit = new ListUnit(); // with default value []

// create a Cluster
const myPrecious = new Cluster({numUnit, strUnit, listUnit})
// using shorthand notation

// static value access
console.log(myPrecious.value())

// and reactive value access, emits whenever a memeber emits
myPrecious.subscribe(value => console.log(value));

// both will immediately log the following
{
  numUnit: 0, strUnit: '', listUnit: []
}

// accessing the Unit through the Cluster
console.log(myPrecious.items.numUnit.value()); // logs 0
```


# Motivation

### Introduction

Ever since the **advent of single-page applications**, we've been handling more and more data on the Frontend, to the point where technologies like GraphQL® are putting Frontend in the driving seat and be done with it. This is all great until you realize that now you have to **fetch, transform, manipulate,** and **manage** all this data in an efficient way on Frontend.

### Problem

Angular, React, Vue, and other similar technologies have made Frontend development so much more versatile and efficient. But at the same time, state-management doesn't seem to be getting any easier.

For efficient state-management, we need a few things

* data structures that are **type-safe**
* data structures that can emit **events on mutation**
* data structures that can **guarantee immutability**
* data structures that can be **persisted through sessions**

JavaScript has none of it, but that's just one part of the problem.

A component built with the **Model-View-Controller** pattern works great until you have to share the Model with other components. That's where the state managers come into the picture. All the shared data now goes through the state-manager, every component gets the data from the state-manager and updates it into the state-manager. But since most mainstream state managers seem to be too verbose, the more you have to use the state-manager the more bloated your codebase becomes, instead of MVC now it becomes **Store-Feature-Reducer-Middleware-Selector-Dispatcher-Effect-View-Controller**. It increases the number of moving parts and bloats up the logic involved in a feature.

The **verbosity** and **obscurity** inherent with most mainstream state management solutions can be intimidating to new developers, and even puzzle and overwhelm the experienced ones. It can become the most complicated part of your app logic very quickly. Then we have to use even more abstract concepts and tools to make sense of this complex structure. It's not uncommon that developers start questioning the need for all this extra complexity and even deem it counter-productive.

Apart from the verbosity and obscurity, another problem is the human brain's limited [working memory](https://en.wikipedia.org/wiki/Working_memory); and having so many abstract concepts distributed in so many files all over the place hinders a developer's performance. Separation of concerns is supposed to make our lives easier not harder.

### Solution

We believe instead of having a single store and so many abstract utility concepts to make the store work, having **independent reactive storage** [**Units**](/activejs/fundamentals/units)**, that closely resemble JavaScript's native data structures** with all the features required for modern state-management built-in, are the answer. Together with a few utilities these Units can achieve everything that is required from a state-manager and do it very efficiently with less code and less confusion.


# Units

**Units** are the most important part of ActiveJS, they are responsible for holding the state of your single page application. Units can also be used independently, without any further knowledge of ActiveJS.

<div align="center"><img src="https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-M8eiu5mJsGJqYjfw_F0%2F-M8f0JyjikwuyoDqgRVD%2FUnits%20Data%20Flow.svg?alt=media&amp;token=2b497a3c-fad9-437b-9037-d326293eff53" alt="Two way data-flow between View Components and a shared Unit."></div>

Units are specialized, reactive data structures based on JavaScript's native data structures like `boolean`, `string` or `array`.&#x20;

For example, [ListUnit](/activejs/fundamentals/units/listunit) is an elaborate `array` like data structure which is also an Observable and implements all the `Array.prototype` methods in a way that, any mutation caused by these methods, emits a new `array` with the mutations applied to it.

The actual value is stored inside the Unit and can be accessed via the `value()` method.

All the available Units are [BoolUnit](/activejs/fundamentals/units/boolunit), [NumUnit](/activejs/fundamentals/units/numunit), [StringUnit](/activejs/fundamentals/units/stringunit), [ListUnit](/activejs/fundamentals/units/listunit), [DictUnit](/activejs/fundamentals/units/dictunit), and [GenericUnit](/activejs/fundamentals/units/genericunit).

### ▶ Initializing a Unit

A Unit has several configuration options, including an optional initial-value.

```typescript
const unit1 = new NumUnit();
// OR
const unit2 = new NumUnit({initialValue: 0});
// OR
const unit3 = new NumUnit({initialValue: 5, cacheSize: 10});
```

Every type of Unit has a designated default value. `NumUnit` has `0` as the default value, and `StringUnit` has `''`. That's why in the above example the `unit1` and `unit2` are equivalent.

### 📑 Accessing the value

```typescript
// static access
console.log(unit1.value()); // logs 0

// reactive access
unit1.subscribe(value => console.log(value)) // logs 0, will log future values

// reactive non-replay access
unit1.future$.subscribe(value => console.log(value)) // will only log future values
```

As you might've noticed, when subscribing to the `unit1`, a value immediately gets logged to the console even though we haven't dispatched any value yet. If you are only interested in future values you can use `future$` Observable, which doesn't replay the last value on subscription, it only emits future values.

### 📡 Dispatching a value

All Units ignore any invalid value dispatch, Units only accept their designated value type, except the [GenericUnit](/activejs/fundamentals/units/genericunit), because it's designed to accept and store all types of values.

```typescript
// initialize
const numUnit = new NumUnit(); // value is 0

// dispatch a new value
numUnit.dispatch(42); // returns true for successful dispatch
// value is 42 now

// using dispatch method with a value-producer function
numUnit.dispatch(currentValue => currentValue + 1);
// value is 43 now

// invalid dispatch
numUnit.dispatch('a string'); // this will be ignored, returns false
// value is still 43
```

There are two ways to dispatch a new value. You can pass a **value** or a **value-producer-function** to generate a new value to the `dispatch` method, the `dispatch` method returns `true` or `false` depending on the success of dispatch, which you can use to make any further decisions.

### 🔙 Using the Cached values

All Units cache 2 values by default, it allows us to go back and forth through these cached-values in such a way that it doesn't affect the cached-values, only the current-value changes. The caching mechanism works almost exactly like browser history.

The cache can be utilized in many ways, but probably the most common use case would be **undo** and **redo** capabilities. For undo feature we can use `goBack` method and for redo we can use `goForward` method respectively.

To dive into more details, see [Caching](/activejs/guides/caching) to understand how it works.

```typescript
// create a Unit with default cache-size of 2
const unit = new StringUnit({initialValue: 'a'}); 

// cache is ['a']

unit.goBack(); // won't work, returns false
unit.goForward(); // won't work, returns false

unit.dispatch('b'); // cache becomes ['a', 'b']
console.log(unit.value()) // logs 'b'

unit.goBack(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'a'

unit.goForward(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'b'

// we can also access all the cached values
console.log(unit.cachedValues()) // logs ['a', 'b']

// or check the current cache index
console.log(unit.cacheIndex) // logs 1

// or check the count of cached values
console.log(unit.cachedValuesCount) // logs 2
```

### ↺ Clear & Reset

Resetting a Unit to it's initial-value is as easy as calling a method. Similarly clearing the value is also that easy.

```typescript
// create a Unit
const unit = new NumUnit({initialValue: 69});

// clear the value
unit.clearValue(); // now value is 0 (the default value for NumUnit)

// reset the value
unit.resetValue(); // now value is 69 again (the initial-value)
```

### 💎 Immutability

To demonstrate immutability we'd need a different kind of Unit because the [NumUnit](/activejs/fundamentals/units/numunit) deals with a primitive type `number` which is already immutable.

Let's take a [ListUnit](https://docs.activejs.dev/fundamentals/units/listunit) to create a reactive, `array` like data structure.

```typescript
// initialize a immutable ListUnit.
const randomList = new ListUnit({immutable: true});
// ListUnit has default initial value []

// subscribe for the value
randomList.subscribe(value => console.log(value));
// logs [] immediately and will log future values
```

We just created an immutable Unit, that's all it takes, a configuration flag.

**✔ Mutation check**

```typescript
const anItem = {type: 'city', name: 'Delhi'};
randomList.push(anItem);
// this push is reactive, it'll make the Unit emit a new value

// let's try mutation by reference
anItem.type = 'state'; // this would work
// but the value of the randomList won't be affected, because every time
// a value is provided to an immutable list,
// it's cloned before storing.

// let's try another approach
const extractedValue = randomList.value(); // get the current value
console.log(listValue); // logs [{type: 'city', name: 'Delhi'}]
// try to mutate the extractedValue
extractedValue[1] = 'let me in...'; // this would work
// but the value of the randomList won't be affected, because every time
// an immutable list provides a value, it's cloned,
// to destroy all references to the stored value.
```

See [Immutability guide](/activejs/guides/immutability) for more details.

### ⚓ Persistence

To make a Unit persistent, all we need is a unique id so that the Unit can identify itself in the `localStorage`, and a configuration flag.

```typescript
// initialize
const persitentUnit = new StringUnit({id: 'userName', persistent: true});
// StringUnit has default inital value ''
```

That's it, this StringUnit is persistent, it already saved its default value to `localStorage`.

**✔ Persistence check**

```typescript
// let's dispatch a new value different than the default value to 
// properly test the persistence
persitentUnit.dispatch('Neo');
console.log(persitentUnit.value()); // logs 'Neo'

// now if we re-initialize the same Unit
// on second initialization the Unit will restore its value from localStorage
// e.g: after a window refresh
console.log(persitentUnit.value()); // logs 'Neo'
```

See [Persistence guide](/activejs/guides/persistence) for more details.

### 🔁 Replay and Replay-ness

Every Unit immediately provides the value when subscribed, by default, but maybe you only want the future values. For that purpose, every Unit has a built-in alternative Observable that doesn't emit immediately on subscription.

```typescript
const unit = NumUnit(); // NumUnit has default initialValue 0

// normal subscription
unit.subscribe(v => console.log(v)) // immediately logs 0

// future only subscription
unit.future$.subscribe(v => console.log(v)) // doesn't log anything

// both will log any future values
unit.dispatch(42); // you'll see two 42 logs in the console
```

You can also turn the default replay-ness off.

```typescript
const unit = NumUnit({replay: false});
// now default Observable and future$ Observable are the same

// normal subscription
unit.subscribe(v => console.log(v)) // doesn't log anything

// future only subscription
unit.future$.subscribe(v => console.log(v)) // doesn't log anything

// both will log any future values
unit.dispatch(42); // you'll see two 42 logs in the console
```

{% hint style="info" %}
By default, every Unit behaves like a [BehaviorSubject](https://www.learnrxjs.io/learn-rxjs/subjects/behaviorsubject), but unlike a BehaviorSubject Units don't require an explicit default value, since a Unit already has a default value.&#x20;
{% endhint %}

### 🔂 Manual Replay

Imagine a Unit is being used as a source for an API request, and you have a "refresh" button to trigger the request again. For this and many other scenarios, Units provide a manual `replay` method.

```typescript
const unit = StringUnit({initialValue: 'Alpha'});

unit.subscribe(v => /*make API request*/); // send every value to the server

unit.dispatch('Sierra'); // send another value

// to emit the same value again, all you have to do is
unit.replay();
// all subscribers will get the same value again, in this case, 'Sierra'
// so the server should receive 'Alpha', 'Sierra', 'Sierra'
```

### ❄ Freezing

If you want a Unit to stop accepting new values, in scenarios where the state is not supposed to change. All you need to do is this:

```typescript
// create a Unit
const unit = DictUnit(); // a DictUnit has default value {}

// freeze the Unit
unit.freeze();

// this will be ignored
unit.dispatch({'nein': 'nein nein'})
// so will any other mutative, or cache-navigation methods
// like goBack(), goForward(), clearValue(), resetValue() etc.

// unfreeze the Unit, and everything will start working again
unit.unfreeze();
```

See [Freezing guide](/activejs/guides/freeze-and-mute) for more details.

### 🔇 Muting

If you want a Unit to stop emitting new values, but keep accepting new values, in scenarios where you aren't interested in new values but still don't want to lose them. All you need to do is mute the Unit.

```typescript
// create a Unit
const unit = GenericUnit(); // a GenericUnit has default value undefined
// it accepts all kinds of values as the name suggests

// mute the Unit
unit.mute();

// this will work
unit.subscribe(value => console.log(value));
// logs undefined immediately, but will not log any new values until unmuted

// this will still work
unit.dispatch('Hello'); // but no subscriber will get triggered

// but if you check the value, you'll get still get the updated value
console.log(unit.value()); // logs 'Hello'

// unmute the Unit, and if the value changed while the Unit was muted,
// emit it to all the subscribers, to bring them in sync
unit.unmute();
```

See [Muting guide](/activejs/guides/freeze-and-mute) for more details.

### 📅 Events

Every Unit emits an event for every operation performed on it, you can tap into these events to take some other action.

```typescript
// create a Unit
const listUnit = new ListUnit();

// subscribe to events
listUnit.events$.subscribe(event => console.log(event));
```

There's an event for almost every operation that can be performed on a Unit, for example:

```typescript
// a succefull dispatch
listUnit.dispatch([69]); // will emit EventUnitDispatch
// an invalid dispatch
listUnit.dispatch({}); // will emit EventUnitDispatchFail
// on freeze
listUnit.freeze(); // will emit EventUnitFreeze
// on ListUnit specific methods
listUnit.push("Hard"); // will emit EventListUnitPush with value "Hard"
// another example
listUnit.pop(); // will emit EventListUnitPop
// and so on...
```

See [Events guide](/activejs/guides/events) for more details.

### 🛠 Units vs native data structures

Units can not be used as drop-in replacements for native data structures. \
However, in most scenarios, a Unit instance can be used directly instead of `Unit.value()`

Every Unit implements [valueOf](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf) and [toString](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/toString) methods. JavaScript automatically invokes these methods when encountering an object where a primitive or string value is expected, respectively. Hence [NumUnit](/activejs/fundamentals/units/numunit), [StringUnit](/activejs/fundamentals/units/stringunit), and [BoolUnit](/activejs/fundamentals/units/boolunit) can be used similar to their primitive counterparts.

Additionally, Units also implement their counterparts prototype methods like [NumUnit](/activejs/fundamentals/units/numunit) implements `Number.prototype` methods to make it easier to work with the stored value. Similarly, [ListUnit](/activejs/fundamentals/units/listunit) implements all the `Array.prototype` methods, [StringUnit](/activejs/fundamentals/units/stringunit) implements all the `String.prototype` methods, and so on.

#### **`number` vs** [**NumUnit**](/activejs/fundamentals/units/numunit)

```typescript
const num = 42069;
const numUnit = new NumUnit({initialValue: 42069});

num.toString() // '42069'
numUnit.toString() // '42069'

num.toLocaleString() // '42,069' (in an 'en' locale)
numUnit.toLocaleString() // '42,069' (in an 'en' locale)

num + 1 // 42070
numUnit + 1 // 42070 // this doesn't change the Unit's value

num + 'XX' // '42069XX'
numUnit + 'XX' // '42069XX' // this doesn't change the Unit's value
```

**`array` vs** [**ListUnit**](/activejs/fundamentals/units/listunit)

```typescript
const arr = ['👽', '👻'];
const listUnit = new ListUnit({initialValue: ['👽', '👻']});

arr.toString() // '👽,👻'
listUnit.toString() // '👽,👻'

arr.join('--') // '👽--👻'
listUnit.join('--') // '👽--👻'

arr.push('🤖') // mutates the same array
listUnit.push('🤖') // this is reactive, creates and dispatches a new array

// ListUnit is also iterable
[...arr] // a shallow copy of arr ['👽', '👻']
[...listUnit] // a shallow copy of stored value ['👽', '👻']

// and every Unit works with JSON.stringify
JSON.stringify({num, arr}) // '{"num":42069, "arr": ["👽", "👻"]}'
JSON.stringify({numUnit, listUnit}) // '{"numUnit":42069, "listUnit": ["👽", "👻"]}'
```

There are even more cases where you can treat a Unit just like a native data structure, barring a few exceptions like [ListUnit](/activejs/fundamentals/units/listunit) and [DictUnit](/activejs/fundamentals/units/dictunit) don't have key-based property access and assignment, they use `get` and `set` methods instead. And the fact that [BoolUnit](/activejs/fundamentals/units/boolunit), [NumUnit](/activejs/fundamentals/units/numunit) or [StringUnit](/activejs/fundamentals/units/stringunit) aren't actually primitives, the `typeof` operator will only return `object`.

#### More Examples

```typescript
const numUnit = new NumUnit({initialValue: 3});
// current value is 3

numUnit + 1 // 4
// is same as this
numUnit.value() + 1 // 4

numUnit + 'idiots' // '3idiots'
// is same as this
numUnit.value() + 'idiots' // '3idiots'

JSON.stringify({n: numUnit}) // {n: 3}
// is same as this
JSON.stringify({n: numUnit.value()}) // {n: 3}


// that's pretty much it, 
// in other situations the Unit will behave like an object, as it should
numUnit === 3 // false
typeof numUnit === 'object' // true
numUnit++ // won't work, it will try to replace numUnit const with number 4

// similarly

const boolUnit = new BoolUnit({initialValue: false});

boolUnit + '' // 'false'
boolUnit + 1 // 1, because false is converted to 0
boolUnit.dispatch(true);
boolUnit + 1 // 2, because true is converted to 1

// similarly

const strUnit = new StringUnit({initialValue: 'Hello'});

strUnit + ' World' // 'Hello World'
strUnit + 1 // 'Hello1'
strUnit.dispatch('6');
parseInt(strUnit) // 6
```

### 📊 Units vs BehaviorSubject

|                                                            | Unit | BehaviorSubject |
| ---------------------------------------------------------- | ---- | --------------- |
| Replays value on subscription                              | ✅    | ✅               |
| Can be configured to not replay value on subscription      | ✅    | ❌               |
| Allows to listen to only future values                     | ✅    | ❌               |
| Accepts an initial-value                                   | ✅    | ✅               |
| Can cache more than one value                              | ✅    | ❌               |
| Allows cache-navigation                                    | ✅    | ❌               |
| Validates dispatched values                                | ✅    | ❌               |
| Specialized for specific data structures                   | ✅    | ❌               |
| Can re-emit/replay last value manually                     | ✅    | ❌               |
| Can be frozen                                              | ✅    | ❌               |
| Can be muted                                               | ✅    | ❌               |
| Can be immutable                                           | ✅    | ❌               |
| Can be persistent                                          | ✅    | ❌               |
| Can be reset                                               | ✅    | ❌               |
| Can be part of a [Cluster](/activejs/fundamentals/cluster) | ✅    | ❌               |

## Configuration Options

The configuration options can be passed at the time of instantiation. All the configuration options are optional. You can set them per Unit or you can also set most of them globally. See [Configuration](/activejs/guides/configuration) for more details.


# BoolUnit

**BoolUnit** is a type of [Unit](/activejs/fundamentals/units) that only accepts `boolean` data type as its value. It ensures that at any point of time the value would always be `boolean`.

It implements non-deprecated [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) methods like `toString`&#x20;and redirects them to the stored `boolean` value inside the Unit, so when you call `BoolUnit.toString()` , it'll be executed on the Unit's value instead of the BoolUnit instance itself. Similarly, when you call other `Object.prototype` methods they are called on the stored value instead of BoolUnit instance.

See [API reference](https://api.activejs.dev/classes/boolunit) for more details.

|                 |           |
| --------------- | --------- |
| Default value   | `false`   |
| Value data type | `boolean` |

### BoolUnit vs `boolean`

BoolUnit can not be used as a drop-in replacement for primitive `boolean` value, since BoolUnit is a non-primitive data structure, and the actual `boolean` value is stored inside the Unit. See the below comparisons for more clarity.

```typescript
// initialization
let bool = false; // a variable with prmitive boolean value
const unit = new BoolUnit({initialValue: false});
// initialValue is optional, BoolUnit has false as default value

bool === unit // false
bool === unit.value() // true

unit + '' // 'false'
unit + 1 // 1, because false is converted to 0
unit.dispatch(true);
unit + 1 // 2, because true is converted to 1

typeof bool === 'boolean' // true
typeof unit === 'object' // true
typeof unit.value() === 'boolean' // true

// value assignment
bool = true;
unit.dispatch(true);

// value access
console.log(bool) // logs true
console.log(unit.value()) // logs true
// or
unit.subscribe(value => console.log(value)) // logs true, will log future values
```


# NumUnit

**NumUnit** is a type of [Unit](/activejs/fundamentals/units) that only accepts `number` data type as its value. It ensures that at any point of time the value would always be `number`.&#x20;It doesn't even accept `NaN` as it's value.

It implements all the [Number.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number) methods available in the environment/browser, including polyfills.\
e.g.:`toFixed` and `toString`, and redirects them to the stored `number` value inside the Unit, so when you call `Unit.toString()` , it'll be executed on the Unit's value instead of the NumUnit instance itself.

See [API reference](https://api.activejs.dev/classes/numunit) for more details.

|                 |          |
| --------------- | -------- |
| Default value   | `0`      |
| Value data type | `number` |

### NumUnit vs `number`

NumUnit can not be used as a drop-in replacement for primitive `number` value, since NumUnit is a non-primitive data structure, and the actual `number` value is stored inside the Unit. See the below comparisons for more clarity.

```typescript
// initialization
let num = 42069; // a variable with prmitive number value
const unit = new NumUnit({initialValue: 42069});
// initialValue is optional, NumUnit has 0 as default value

num === unit // false
num === unit.value() // true

num.toString() // '42069'
numUnit.toString() // '42069'

num.toLocaleString() // '42,069' (in an 'en' locale)
numUnit.toLocaleString() // '42,069' (in an 'en' locale)

num + 1 // 42070
numUnit + 1 // 42070 // this doesn't change the Unit's value

num + 'XX' // '42069XX'
numUnit + 'XX' // '42069XX' // this doesn't change the Unit's value

typeof num === 'number' // true
typeof unit === 'object' // true
typeof unit.value() === 'number' // true

// value assignment
num = 7;
unit.dispatch(7);

// value access
console.log(num) // logs 7
console.log(unit.value()) // logs 7
// or
unit.subscribe(value => console.log(value)) // logs 7, will log future values
```


# StringUnit

**StringUnit** is a type of [Unit](/activejs/fundamentals/units) that only accepts `string` data type as its value. It ensures that at any point of time the value would always be `string`.

It implements all the [String.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String) methods available in the environment/browser, including polyfills.\
e.g.: `trim`, `includes` and `toLowerCase`, etc., and redirects them to the stored `string` value inside the Unit, so when you call `Unit.includes()` , it'll be executed on the Unit's value instead of the Unit instance itself.&#x20;

When we use `String.prototype` methods like `replace`, it doesn't mutate the value of the Unit, similar to how simple `String.prototype.replace` works.

See [API reference](https://api.activejs.dev/classes/stringunit) for more details.

|                 |                     |
| --------------- | ------------------- |
| Default value   | `''` (empty string) |
| Value data type | `string`            |

### StringUnit vs `string`

StringUnit can not be used as a drop-in replacement for primitive `string` value, since StringUnit is a non-primitive data structure, and the actual `string` value is stored inside the Unit, which can be accessed via`Unit.value()` method. See the below comparisons for more clarity.

```typescript
// initialization
let str = 'Hello';
const unit = new StringUnit({initialValue: 'Hello'});

str === unit // false
str === unit.value() // true

unit + ' World' // 'Hello World'
unit + 1 // 'Hello1'
unit.dispatch('6');
parseInt(unit) // 6

typeof str === 'string' // true
typeof unit === 'object' // true
typeof unit.value() === 'string' // true

// value assignment
str = 'bye';
unit.dispatch('bye');

// value access
console.log(str) // logs 'bye'
console.log(unit.value()) // logs 'bye'
// OR
unit.subscribe(value => console.log(value)) // logs 'bye', will log future values
```


# DictUnit

**DictUnit** is a type of [Unit](/activejs/fundamentals/units) that only accepts plain, non-null, non-Array, key-value based `object` data type as its value. It ensures that at any point of time the value would always be a dictionary `object`.&#x20;It's loosely based on [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map). DictUnit has some similar methods as the Map, but that's where the similarities end. For one thing, the keys in DictUnit value can only be of type `string` since the underlying data structure is still a simple `object` not a `Map`.

It borrows some [Map.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) methods like `set` , `has`,  `get` etc. \
However, these methods aren't exactly the same, there are some differences as we explained above.

It also implements non-deprecated [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) methods like `hasOwnProperty`, and redirects them to the stored `object` value inside the Unit, so when you call `DictUnit.hasOwnProperty('prop')` , it'll be executed on the Unit's value instead of the Unit instance itself. But there's probably no need to call it, you can just use `DictUnit.has('prop')` instead.

It also borrows some static methods from [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#) like `assign` and `entries`, and implements them as instance members `assign` and `objectEntries`, respectively. These methods operate on the stored object value instead of the Unit instance itself.&#x20;

See [API reference](https://api.activejs.dev/classes/dictunit) for more details.

|                 |                           |
| --------------- | ------------------------- |
| Default value   | `{}`                      |
| Value data type | plain dictionary `object` |

### DictUnit vs `object` literal vs `Map`:

DictUnit can not be used as a drop-in replacement for a dictionary `object` or `Map`. You can not directly assign or access properties like `unit[k] = v` instead, you have to use `unit.set('k', v)` and `unit.get('k')`, respectively. Unlike a Map, the keys can only be of type `string` as the underlying data structure is still a simple `object`. See the below comparisons for more clarity.

```typescript
// initialization
const obj = {a: 1}; // an object literal
const map = new Map([['a', 1]]); // a map with a key:value pair 'a':1
const unit = new DictUnit({initialValue: {a: 1}}); // value is {a: 1}

obj === map // false
obj === unit // false
map === unit // false

typeof obj === 'object' // true
typeof map === 'object' // true
typeof unit === 'object' // true
unit instanceof Map // false

// adding a property
obj.b = 2;
map.set('b') = 2;
unit.set('b') = 2; // this is reactive, creates and dispatches a new object

map.set(obj, unit) // works
map.get(obj) // returns unit
unit.set(obj, map) // won't work, the key has to be a number or string
// additionally, non serialzable values are not recommended,
// when you configure the Unit to be immutable, 
// the Unit will create a clone of the value but the Map will not be cloned.
// And when you configure the Unit to be persistent, 
// the Unit will save it to localStorage using JSON.stringify but Map doesn't
// work with JSON.stringify, it simply becomes "{}".

map.clear() // clears all the key-value pairs
unit.clearValue() // clears the value and emits the default value {}, 
// this is similar to map.clear()

unit.clear() // clears the value and emits the default value ie: empty {}, 
// it also clears the cache, and unfreezes the unit
```


# ListUnit

**ListUnit** is a type of [Unit](/activejs/fundamentals/units) that only accepts `array` data type as its value. It ensures that at any point of time the value would always be an `array`.

It's based on [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). It implements all the [Array.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array) methods available in the environment/browser, including polyfills. \
e.g.: `push`, `pop`, `join` and `toString`&#x20;etc. to make working with the stored value a bit easier, when you call these methods they are called on the stored `array` value instead of ListUnit instance.

It also borrows some static methods from [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#) like `values` and `entries`, and implements them as instance members `objectValues` and `objectEntries`, respectively.&#x20;

See [API reference](https://api.activejs.dev/classes/listunit) for more details.

|                 |         |
| --------------- | ------- |
| Default value   | `[]`    |
| Value data type | `array` |

### ListUnit vs `array`

ListUnit can not be used as a drop-in replacement for an `array`. You can not directly assign or access properties like `unit[index] = v` instead, you have to use `unit.set(index, v)` and `unit.get(index)`, respectively. See the below comparisons for more clarity.

Apart from that, all the non-mutating methods like `map`, `find`, `findIndex`, etc. work similar to as they would on an array. However mutating-methods have some differences, for one, every mutating method makes the Unit emit a new array instead of mutating the current value.&#x20;

Also, `forEach` method has been replaced with `forEvery`, because the extended `Observable` class already has a `forEach` method that is intended for something else entirely. See [API reference](http://localhost:8080/globals.html) for more details.

```typescript
// initialization
const arr = ['🐠']; // an array literal
const unit = new ListUnit({initialValue: ['🐠']}); // value is ['🐠']

arr === unit // false

arr instanceof Array // true
unit instanceof Array // false
Array.isArray(unit) // false

// setting an item
arr[1] = '🐞'
unit.set(1) = '🐞' // this is reactive, creates and dispatches a new array

// pushing an item
arr.push('🐊')
unit.push('🐊') // this is reactive, creates and dispatches a new array

// accessing an item at index 0
arr[0]
unit.get(0)
// or 
unit.first()

// removing an item at index 1
arr.splice(1, 1)
unit.splice(1, 1)
// or
unit.remove(1)
```


# GenericUnit

**GenericUnit** is a type of [Unit](/activejs/fundamentals/units) that doesn't pertain to any specific data type, it's generic, as the name suggests. You can use it to store any serializable value data type that other Units accept. i.e.: `boolean`, `number`, `string`, simple `object` and `array`.

The advantage of using **GenericUnit** over other **Units** is that you can store and `dispatch` any type of value and the disadvantage is that you lose the specialized methods and features built into other Units for a specific data structure, for example, we can store an `array` value in a **GenericUnit**, but we cannot use methods like `push` or `set` to add items to the value without a manual `dispatch`. Also, we lose the assurance that the value would always be of a specific data type, i.e.: an `array` in case of **ListUnit**.

GenericUnit implements non-proto [Object.prototype](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object) methods like `toString`&#x20;to make working with the stored value a bit easier, when you call these methods they are called on the stored value instead of GenericUnit instance.

It also borrows some static methods from [Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object#) like `values` and `entries`, and implements them as instance members `objectValues` and `objectEntries`, respectively.  These methods do not throw an error on `undefined` or `null` value, they would simply return an empty array instead.

See [API reference](https://api.activejs.dev/classes/genericunit) for more details.

|                      |                                                               |
| -------------------- | ------------------------------------------------------------- |
| Default value        | `undefined`                                                   |
| Supported data types | `boolean`, `number`, `string`, serializable `object`, `array` |

```typescript
// initialization
const unit = new GenericUnit({initialValue: ['🐠']}); // value is ['🐠']

typeof unit === 'object' // true
unit instanceof Array // false
unit.value() instanceof Array // true

// adding an item to the stored array value
unit.dispatch(arrValue => [...arrValue, '🐞'])
// this is inefficient compared to ListUnit.push, but it works

// dispatching a different type of value
unit.dispatch('not an array') // works

// dispatching a different type of value
unit.dispatch(true) // works
```


# Systems

Systems are nothing but a specialized combination of a few Units, a System creates a few predefined relationships among its member Units to make them part of a whole.

While the Units are storage mediums, Systems are task helpers.

A System tries to accomplish a specific type of task (*that has multiple aspects to it, and hence requiring multiple Units to work in cohesion*) in a reactive and shared fashion, such as data fetching using `XHR` API, or `fetch` API. Both of these APIs or any other asynchronous API more or less involve a **query**, a successful **response**, an **error**, and **pending-status** of the task.&#x20;

The [AsyncSystem](/activejs/fundamentals/systems/asyncsystem) is the System that is built to help with these kinds of asynchronous APIs.

{% content-ref url="/pages/-M6aLGid7csUtSOcDjGY" %}
[AsyncSystem](/activejs/fundamentals/systems/asyncsystem)
{% endcontent-ref %}


# AsyncSystem

An **AsyncSystem** is a systematic combination of four Units, one each for every aspect of an asynchronous task or API, e.g.: **XHR**, **fetch** or a third party abstraction like Angular's **HttpClient.**

The four aspects of an async API are **query**, **response**, **error**, and **pending-status**. For each of these aspects, we have a Unit, wrapped inside the AsyncSystem.

AsyncSystem employs three [GenericUnits](/activejs/fundamentals/units/genericunit) for **query**, **response,** and **error**, namely `queryUnit`, `dataUnit`, and `errorUnit`, respectively; and a [BoolUnit](/activejs/fundamentals/units/boolunit) for the **pending-status,** named `pendingUnit`.

A BoolUnit is used for the pending-status because it can only be in two states, `true` or `false`

GenericUnit is used for the other three aspects because it's the most permissive of all the Units, and it saves us from creating multiple variations with different kinds of Units. However, you can [substitute the GenericUnits](/activejs/fundamentals/systems/custom-asyncsystem) with a different kind of Unit if you want and create your own [custom AsyncSystem](/activejs/fundamentals/systems/custom-asyncsystem), very easily.

The below diagram shows where and how AsyncSystem helps with an asynchronous API call to the server, and how the data flow looks like, and how the AsyncSystem shares the API call's state with multiple parts of the App.

![The data flow diagram of an async API call involving an AsyncSystem.](https://1597575908-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M6W6qxSNpirGD4JLBmY%2F-MAsFH3yDU9S0O2wrt5E%2F-MAus9ja8m4KTHAAnej8%2FAsyncSystem%20Data%20Flow.svg?alt=media\&token=13c011a4-2296-4afb-88e3-1fe68a81b175)

It might seem like a lot, but not everything is happening at the same time. When you break it down it's not difficult to understand.

* The data flow starts with a dispatch to the `queryUnit`, which triggers an API call from the **API Service**.
* The **API Service** contains the logic of listening to the `queryUnit`, making the actual API call, and then submitting its result back to the **AsyncSystem**, appropriately.
* On a successful response, the **API Service** dispatches the response received, to the `dataUnit`.
* On an error response, the **API Service** dispatches the error to the `errorUnit`.
* The `pendingUnit` is updated automatically by the AsyncSystem, it's given a `true` value when `queryUnit` emits, and a `false` value when `dataUnit` or `errorUnit` emits a value.

That's pretty much it, this is how an AsyncSystem works.

There are other automatic things that an AsyncSystem can do apart from updating the value of `pendingUnit`. Such as, it can clear the `errorUnit`'s value when `dataUnit` emits a value. It can `freeze` the `queryUnit` while the `pendingUnit` has a `true` value, etc.

See [API reference](https://api.activejs.dev/classes/asyncsystem) for more details.

This is how the usage of AsyncSystem would look like in Angular and React apps.

### Angular

{% tabs %}
{% tab title="user.state.ts" %}

```typescript
import {Injectable} from '@angular/core';
import {HttpErrorResponse} from '@angular/common/http';
import {AsyncSystem} from '@activejs/core';

@Injectable({providedIn: 'root'})
export class UserState {

  // initialize an AsyncSystem and declare the typings such that
  // query would be a number,
  // data would be a string,
  // error would be an HttpErrorResponse object
  readonly userSystem = new AsyncSystem<number, string, HttpErrorResponse>();
  
  // extract the Units for ease of access, or don't if you prefer
  readonly userQuery = this.userSystem.queryUnit;
  readonly userData = this.userSystem.dataUnit;
  readonly userError = this.userSystem.errorUnit;
  readonly userPending = this.userSystem.pendingUnit;
}
```

{% endtab %}

{% tab title="user.streams.ts" %}

```typescript
import {Injectable} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {EMPTY, Observable} from 'rxjs';
import {catchError, switchMap, tap} from 'rxjs/operators';
import {UserState} from './user.state';

// Create a separate service for Streams, it helps avoid cyclic dependencies.
// It'll do all the heavy lifting, it'll make http requests and
// dispatch the results to the userDataSystem.

@Injectable() // we'll instantiate it in user.module.ts so no "provideIn"
export class UserStreams {

  // create a Stream using the userSystem and couple it with an http request
  userDataStream = this.userState.userSystem.createStream(
    (
      queryUnit, dataUnit, errorUnit
    ) => {
      // listen to the future values of queryUnit
      return queryUnit.future$.pipe(
      // you can also do queryUnit.pipe, but that'll start immediately,
      // without even dispatching anything to queryUnit
  
        // switch the stream to http request Observable
        // to create a new request
        switchMap(userId => this.httpClient
          .get('https://example.com/username' + userId)
          .pipe(
            // dispatch the returned data to dataUnit
            tap(data => dataUnit.dispatch(data)),
    
            // catch the error
            catchError(err => {
    
              // dispatch the error to errorUnit
              errorUnit.dispatch(err);
    
              // don't rethrow, to keep the stream alive
              return EMPTY;
            })
          )
        ));
  });

  constructor(
    private httpClient: HttpClient, 
    private userState: UserState
  ) {}
}
```

{% endtab %}

{% tab title="user.component.ts" %}

```typescript
import {Component} from '@angular/core';
import {UserState} from './user.state';

/* 
  An Angular component.
  It will trigger the API request and show the response 
  along with loading-state.
*/

@Component({
  selector: 'app-user',
  templateUrl: 'user.component.html'
})
export class UserComponent {
  userId: number;

  constructor(public userState: UserState) {}

  loadData() {
    this.userState.userQuery.dispatch(this.userId);
  }

  reloadData() {
    this.userState.userQuery.replay();
  }
}
```

{% endtab %}

{% tab title="user.component.html" %}

```markup
<!--> 
  The template for Angular component.
</-->

<h1>Load data from a REST API using AsyncSystem.</h1>

<input type="number" [(ngModel)]="userId">

<button (click)="loadData()">Load Data</button>
<button (click)="reloadData()">Reload Data</button>

<p *ngIf="userState.userPending | async">
  Loading...
</p>

<p *ngIf="userState.userData | async as name">
  My name is: {{name}}
</p>

<p *ngIf="userState.userError | async as error">
  Error: {{error.message}}
</p>
```

{% endtab %}

{% tab title="user.module.ts" %}

```typescript
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {UserStreams} from './user.streams';
import {UserComponent} from './user.component';

// here we are creating a Feature Module, so we're making the UserStreams part of
// this module only, so they start working when this Module is used.
// But if we had more generic Streams-service we can do the same
// in the AppModule so that the Streams start when the app starts.

@NgModule({
  declarations: [UserComponent],
  imports: [CommonModule],
  providers: [
    // make the UserStreams part of dependecy injection
    UserStreams,
    // instantiate the UserStreams service using APP_INITILIZER, or
    // we can do it in old fashioned way by putting in the contructor of AppModule
    {
      provide: APP_INITIALIZER,
      useFactory: () => () => {},
      deps: [UserStreams], // we can put as many Streams services here as we want
      multi: true,
    },
  ]
})
export class UserModule {}
```

{% endtab %}
{% endtabs %}

See this [Typeahead](https://activejs.dev/#/examples/typeahead) example to for real-life usage.

### React

This is how a typical usage would look like, using the React Hooks, and a custom Hook for using ActiveJS Units and Observables called [useObservable](/activejs/integrations/react/useobservable-hook).

{% tabs %}
{% tab title="user.state.ts" %}

```typescript
import {AsyncSystem} from '@activejs/core';

// initialize an AsyncSystem and declare the typings such that
// query would be a number,
// data would be a string,
// error would be an HttpErrorResponse object
export const userSystem = new AsyncSystem<string, string, any>();

// extract the Units for ease of access, or don't if you prefer
export const userQueryUnit = userSystem.queryUnit;
export const userDataUnit = userSystem.dataUnit;
export const userErrorUnit = userSystem.errorUnit;
export const userPendingUnit = userSystem.pendingUnit;
```

{% endtab %}

{% tab title="user.streams.ts" %}

```typescript
// Create a separate file for Streams, it helps avoid cyclic dependencies.
// It'll do all the heavy lifting, it'll make http requests and
// dispatch the results to the userDataSystem.

import {EMPTY, Observable} from 'rxjs';
import {catchError, switchMap, tap} from 'rxjs/operators';
import {queryUnit, dataUnit, errorUnit} from './user.state';

// a function to fetch data and disptch the response appropriately
async function fetchAndShareData(query) {
  try {
    // fetch data using fetch API
    const response = await fetch('https://xyz.com/u/' + query.userId);
    // extract the JSON data
    const data = await response.json();

    // dispatch data to the dataUnit, it also sets the pendingUnit's value to false
    // and it also clears the errorUnit's value
    dataUnit.dispatch(data);
  } catch (err) {
    // dispatch error to errorUnit, it also sets the pendingUnit's value to false
    errorUnit.dispatch(err);
  }
}

// setup the stream by observing query values, that triggers fetchAndShareData
// whenever a value is dispatched to queryUnit
queryUnit.subscribe(query => fetchAndShareData(query));
```

{% endtab %}

{% tab title="user.component.tsx" %}

```typescript
/* 
  A React component.
  It will trigger the API request and show the response 
  along with loading-state.
*/
function App() {
  const [userId, setUserId] = useState('');
  
  const data = useObservable(userDataUnit);
  const isPending = useObservable(userPendingUnit);
  const error = useObservable(userErrorUnit);

  const loadData = () => userQueryUnit.dispatch(userId);
  const reloadData = () => userQueryUnit.replay();

  return (
    <React.Fragment>
      <h1>Load data from a REST API using AsyncSystem.</h1>
      {userId}

      <input type="number" onChange={e => setUserId(e.target.value)}/>

      {isPending && <p>Loading...</p>}

      {data && <p>My name is: {data}</p>}

      {error && <p>Error: {error}</p>}

      <button onClick={loadData}>Load Data</button>
      <button onClick={reloadData}>Reload</button>
    </React.Fragment>
  );
}
```

{% endtab %}
{% endtabs %}

See this [Typeahead](https://stackblitz.com/edit/react-ts-spn9ze?file=index.tsx) example to for real-life usage.

## Configuration Options

The configuration options can be passed at the time of instantiation. All the configuration options are optional. Most of the options can also be set globally. See [Configuration](/activejs/guides/configuration) for more details.


# Custom AsyncSystem

ActiveJS exposes an [AsyncSystemBase](https://api.activejs.dev/classes/asyncsystembase) class that can be used to create customized [AsyncSystem](/activejs/fundamentals/systems/asyncsystem) like [Systems](/activejs/fundamentals/systems/custom-asyncsystem).

One limitation of [AsyncSystem](/activejs/fundamentals/systems/asyncsystem) is that it doesn't let you change the type of [Units](/activejs/fundamentals/units) used by it. \
With [AsyncSystemBase](https://api.activejs.dev/classes/asyncsystembase) you can create your own AsyncSystem like Systems and use any type of Unit you want as `queryUnit`, `dataUnit` and `errorUnit`.

AsyncSystemBase can be utilized in two ways,

## 1. Direct Usage

Instead of creating an instance of [AsyncSystem](/activejs/fundamentals/systems/asyncsystem) where the [Units](/activejs/fundamentals/units) are created internally, you can create the Units yourself and pass them to the [AsyncSystemBase](https://api.activejs.dev/classes/asyncsystembase) directly.

```typescript
const customAsyncSystem = new AsyncSystemBase(
  new ListUnit<string>(), // queryUnit
  new DictUnit<{ a: number, b: string }>(), // dataUnit
  new GenericUnit<number>(), // errorUnit
  new BoolUnit(), // pendingUnit
  {clearErrorOnData: false} // config is optional
);

// extract the Units from the System
const {queryUnit, dataUnit, errorUnit, pendingUnit} = customAsyncSystem;

// confirm the type of Units
queryUnit instanceof ListUnit // true
dataUnit instanceof DictUnit // true
errorUnit instanceof GenericUnit // true
pendingUnit instanceof BoolUnit // true
```

## 2. Extend the AsyncSystemBase class

If you don't want to create Units every time you want to create a custom AsyncSystem, you can extend the base class and do the same thing that [AsyncSystem](/activejs/fundamentals/systems/asyncsystem) does, abstract away the Unit creation in the extended class and only accept typings through generics. This will allow you to be more efficient while still staying flexible.

**Example:** Create a custom AsyncSystem that uses [ListUnit](/activejs/fundamentals/units/listunit) as `queryUnit`, [DictUnit](/activejs/fundamentals/units/dictunit) as `dataUnit` and [GenericUnit](/activejs/fundamentals/units/genericunit) as `errorUnit`.

### Implementation:

```typescript
// accept the types for queryUnit, dataUnit and erroUnit as generics
export class CustomAsyncSystem<Query, Data, Error>

// extend the base class and pass the Units with types as generics
extends AsyncSystemBase<ListUnit<Query>, DictUnit<Data>, GenericUnit<Error>> {

  // accept config options optionally to pass them to the base class
  constructor(config?: AsyncSystemBaseConfig<Query, Data, Error>) {
 
    // create the Units and pass them to the base class along with the config
    super(
       new ListUnit(), 
       new DictUnit(),
       new GenericUnit(),
       new BoolUnit(),
       config
    );
 }
}
```

### Usage:

```typescript
type QueryType = number; // type for queryUnit's value
type DataType = string; // type for dataUnit's value
type ErrorType = {status: number, message: string}; // type for errorUnit's value

// initialize a CustomSyncSystem, pass the types as generics
const customSystem = new CustomAsyncSystem<QueryType, DataType, ErrorType>();
// that's it

// checking the types of Units
queryUnit instanceof ListUnit // true
dataUnit instanceof DictUnit // true
errorUnit instanceof GenericUnit // true
pendingUnit instanceof BoolUnit // true
```

## Notes

When using a custom AsyncSystem, directly or by extending, there are a few things that you should keep in mind, to get the expected results.

[AsyncSystem](/activejs/fundamentals/systems/asyncsystem) uses [GenericUnit](/activejs/fundamentals/units/genericunit) because it's very permissive in what it accepts as its value while other Units only allow a specific data type, this difference in behavior might cause a hung state, for example, if we use a [DictUnit](/activejs/fundamentals/units/dictunit) as the `dataUnit` and we try to dispatch an `array` value, it will get ignored and any observer expecting a new value wouldn't receive it. Additionally, `pendingUnit` wouldn't be updated automatically. (i.e. It'll stay `true` until successful data or error dispatch)

To mitigate this problem, when using a non-[GenericUnit](/activejs/fundamentals/units/genericunit) as a `dataUnit` or `errorUnit`, ensure that the value being dispatched is valid and will be dispatched. Every Unit has a `wouldDispatch` method for exactly this kind of scenario.


# Action

Actions are meant to represent unique reactive events. Action is an RxJS [Subject](https://rxjs.dev/guide/subject) like construct.\
Actions don't replay the last value when subscribed to, unlike [Units](/activejs/fundamentals/units), [Systems](/activejs/fundamentals/systems) and [Clusters](/activejs/fundamentals/cluster).\
Actions help trigger customized operations in a reactive fashion.

You can call an Action a simplified form of a Unit as they share the same base API, although configured in a slightly different way.

* It has a `dispatch` method, just like a [Unit](/activejs/fundamentals/units).

* It extends the RxJS Observable class, hence it's an Observable.

* By default, It doesn't replay when subscribed to, unlike a Unit.

* It doesn't require an initial value, yet provides direct access to the last emitted value, just like a Unit.

* It can only cache one value at a time, unlike a Unit.

* Unlike Units, it doesn't perform any checks on `dispatch`.

See [API reference](https://api.activejs.dev/classes/action) for more details.

### Initializing an Action:

```typescript
// create an Action, that accepts number as its value
const multiplyAction = new Action<number>();
```

Action is an Observable but not a Subject.

```typescript
multiplyAction instanceof Subject // false 
multiplyAction instanceof Observable // true
```

### Accessing the value:

```typescript
// access the value
console.log(multiplyAction.value()) // logs undefined

// dynamically access the value
multiplyAction.subscribe(value => {
  console.log(value) // will log future values
  // do something with the value here
});
```

### Dispatching a value:

```typescript
// dispatch a value
multiplyAction.dispatch(3);

// replay the value
multiplyAction.replay(); // multiplyAction emits 3 again
```

The above example shows the basic usage of an Action, it's similar to an RxJS Subject with slight differences.

### Creating a stream:

The real-life usage would most probably be to create streams using the Action.

```typescript
// create a NumUnit to apply the multiplyAction on it
const numUnit = new NumUnit({initialValue: 10})


// create a stream using the earlier Action and above Unit
const subscription = multiplyAction.pipe(
  tap(multiplier => {
    // multiply the numUnit's value and update it
    numUnit.dispatch(currValue => currValue * multiplier)
  })
).subscribe();


// or simply use the built-in createStream method
const stream = multiplyAction.createStream(action$ => {
  return action$.pipe(
    tap(multiplier => {
      // multiply the numUnit's value and update it
      numUnit.dispatch(currValue => currValue * multiplier)
    })
  )
})
```

The advantage of using the `createStream` method is that we get a [Stream](/activejs/utilities/stream) instance.\
So we can stop and re-start the multiplication stream.

```typescript
// stop the multiplication stream
stream.unsubscribe();

// re-start the multiplication stream
stream.resubscribe();
```

## Action vs Units vs BehaviorSubject

|                                                                                                        | Action | Unit | BehaviorSubject |
| ------------------------------------------------------------------------------------------------------ | ------ | ---- | --------------- |
| Replays value on subscription (by default)                                                             | ❌      | ✅    | ✅               |
| Can be configured to replay value on subscription                                                      | ✅      | ✅    | ❌               |
| <p>Allows to listen to only future values</p><p>(useful when configured to replay on subscription)</p> | ✅      | ✅    | ❌               |
| Accepts an initial-value                                                                               | ✅      | ✅    | ✅               |
| Can cache more than one value                                                                          | ❌      | ✅    | ❌               |
| Validates dispatched values                                                                            | ❌      | ✅    | ❌               |
| Can re-emit/replay last value manually                                                                 | ✅      | ✅    | ❌               |
| Can be part of a [Cluster](/activejs/fundamentals/cluster)                                             | ✅      | ✅    | ❌               |

## Configuration Options

The configuration options can be passed at the time of instantiation. All the configuration options are optional. Some options can also be set globally. See [Configuration](/activejs/guides/configuration) for more details.


# Cluster

A Cluster is just a wrapper, a group, of two or more ActiveJS fundamental constructs, [Units](/activejs/fundamentals/units), [Systems](/activejs/fundamentals/systems), [Actions](/activejs/fundamentals/action), or even [Clusters](/activejs/fundamentals/cluster).

It creates a master Observable of the combined value of its members by merging all the provided Observable constructs. Whenever any of these wrapped constructs emits a value, Cluster emits a new combined-value.

It also provides direct access to the wrapped constructs through `items` property.\
The ideal use case would be when you need access to the combined value of some ActiveJS constructs as an Observable.

Basically,

* It creates a master Observable of the combined -value of provided members.
* Provides access to its members through the Cluster.
* Provides static access to the combined-value.

See [API reference](https://api.activejs.dev/classes/cluster) for more details.

### Initializing a Cluster:

```typescript
// a ListUnit that saves user's liked things
const userLikesUnit = new ListUnit();

// a DictUnit that saves user's preferences as key:value pairs
const userPreferencesUnit = new DictUnit({initialValue: {humor: 'dark'}});

// create a Cluster to group the above Units together
const userDataCluster = new Cluster({
    userLikesUnit, // using shorthand notation
    userPreferencesUnit
});
```

### Accessing the value:

```typescript
// subscribe for the combined-value
userDataCluster.subscribe(value => console.log(value))

// or access it directly
console.log(userDataCluster.value())

// both of these will log the following
{
    userLikesUnit: [],
    userPreferencesUnit: {humor: 'dark'}
}
```

### Accessing the members through Cluster:

Cluster members can be accessed through the `items` property.

```typescript
console.log(userDataCluster.items.userPreferencesUnit.value());
// logs {humor: 'dark'}

console.log(userDataCluster.items.userLikesUnit.value());
// logs []
```

### **Value propagation:**

Whenever a member of the Cluster emits a value, the Cluster will emit a new combined value.

```typescript
// set a preference to the userPreferencesUnit
userPreferencesUnit.set('favouriteMovie', 'Matrix');

// the Cluster will emit the following value
{
    userLikesUnit: [],
    userPreferencesUnit: {humor: 'dark', favouriteMovie: 'Matrix'}
}



// add some liked things to the userLikesUnit
userLikesUnit.push({id: 42, label: 'puppy'}, {id: 66, label: 'kitten'});

// the Cluster will emit the following value
{
    userLikesUnit: [{id: 42, label: 'puppy'}, {id: 66, label: 'kitten'}],
    userPreferencesUnit: {humor: 'dark', favouriteMovie: 'Matrix'}
}

```

Similarly, we can group any number of Units, Systems, Actions or even Clusters together.

## Notes

* Try to refrain from using the static value accessor `value()` method when the Cluster contains immutable Units because when calling the `value()` method of a Cluster, it internally calls its members' `value()` method, and if members are Immutable Units, those Units would create a clone on every call. It's not a bad thing if used intentionally, but it can add extra overhead if used too often.

## Configuration Options

The configuration options can be passed at the time of instantiation. All the configuration options are optional. Some options can also be set globally. See [Configuration](/activejs/guides/configuration) for more details.


# Stream

Stream is a simple construct that creates a subscription by subscribing to the provided Observable and adds the ability to re-subscribe.

Given an Observable, the Stream immediately subscribes to it. The `Subscription` instance is saved as Stream's property. The Stream keeps the reference to the provided Observable and uses it for re-subscription when asked.

See [API reference](https://api.activejs.dev/classes/stream) for more details.

### Class Signature

```typescript
class Stream {
    constructor(observable: Observable<any>){
    }
}
```

### Explicit Usage Example

```typescript
import {timer} from 'rxjs';
import {tap} from 'rxjs/operators';
import {Stream} from '@activejs/core';

// create a cold Observable that emits at a 1-second interval.
// RxJS timer emits incremental numbers starting from 0
const randomNumberLogger$ = timer(0, 1000).pipe(
    tap(count => console.log(count))
);

// create a Stream using the randomNumberLogger$
const randomNumberStream = new Stream(randomNumberLogger$);

// each passing second we'll see a number logged in console
// 0, 1, 2, 3, and so on

// restart the timer
randomNumberStream.resubscribe();

// and the timer will start again
// again we'll see 0, 1, 2, 3, and so on

// you can also stop the stream similar to a simple Subscription
randomNumberStream.unsubscribe();
```

### Implicit Usage Example

Stream is implicitly used to create streams when you call `createStream` on an Action, Unit, System, or Cluster.

```typescript
// initialize an Action, that accepts a value of type 'A' | 'B' | 'C'
const anAction = new Action<'A' | 'B' | 'C'>();

// create stream
const alertStream = anAction.createStream(value$ => {
    return value$.pipe(
        tap(value => {
            alert(value); // or do something else entirely
        })
    );
})

// create another stream
const consoleStream = anAction.createStream(value$ => {
    return value$.pipe(
        tap(value => {
            console.log(value); // or do something else entirely
        })
    );
})

// our setup is complete, now we can dispatch/trigger it from anywhere
anAction.dispatch('A');

// stop the consoleStream
consoleStream.unsubscribe();

// and so on
```


# Selection

[Selection](https://api.activejs.dev/classes/selection.html) is a simple construct that operates on a nested property in the non-primitive Units' value, i.e.: [ListUnit](/activejs/fundamentals/units/listunit), [GenericUnit](/activejs/fundamentals/units/genericunit), and [DictUnit](/activejs/fundamentals/units/dictunit).

Selection offers the ability to access and observe a nested property at a certain path in a Unit's value.

### Make a Selection

```typescript
// create a Unit
const preferencesUnit = new DictUnit({initialValue: 
  {color: 'blue', music: 'EDM', game: 'GTA5'}
})

// make a selection
// the 'select' method takes path as it's params
const musicPreference = preferencesUnit.select('music')
```

### Static Value Access

After creating a Selection object, we can access the value at the selected path anytime, without worrying if the value still exists or not.

```typescript
// access the value at the selected path
console.log(musicPreference.value())
// logs 'EDM' immediately
```

### Reactive Value Access

To observe the value over time we can make an Observable at the selected path, and subscribe to it.

```typescript
// create an Observable
const musicPreference$ = musicPreference.asObservable()

// subsribe for reactive access
musicPreference$.subscribe(value => console.log(value))
// logs 'EDM' immediately, and
// will log whenever the value at the selected path changes
```


# Angular

Using ActiveJS with Angular doesn't require any special bindings or facade, you can treat ActiveJS as an extension of RxJS, and use it in the same way.

That being said, you should still try to follow the [general guidelines](/activejs/guides/code-style) regarding how you structure your code.

In addition to general guidelines, one thing specific to Angular is DI and Services. So. instead of directly exporting the Units and other ActiveJS constructs from a file, you put them in a Service.

Generally, you can keep all the ActiveJS constructs like [Units](/activejs/fundamentals/units) and [Streams](/activejs/utilities/stream) together in a single Service, but as your App grows larger, it can become a little messy and you might run into cyclic dependencies pretty quickly, in order to avoid that, this is what ActiveJS recommends.

Ideally, you'd have two to three Services, 2 for State Management (ActiveJS) and 1 for general business logic or Angular related logic.

1. `[feature].state.ts`\
   The **FeatureState** Service holds our **state** objects, i.e.: [Units](/activejs/fundamentals/units), [Actions](/activejs/fundamentals/action), [Systems](/activejs/fundamentals/systems), and [Clusters](/activejs/fundamentals/cluster).<br>
2. `[feature].streams.ts`\
   The **FeatureStreams** Service contains all the **side-effects** built using [Streams](/activejs/utilities/stream) and Angular's `HttpClient`.<br>
3. `[feature].service.ts`\
   The **FeatureService** is an optional Service, which can contain any custom logic depending on your use-case.

For example, if we have a feature called **Auth**, we would create 3 Services like this:

1. `auth.state.ts` **-** with Service name **AuthState**
2. `auth.streams.ts` **-** with Service name **AuthStreams**
3. `auth.service.ts` **-** with Service name **AuthService**

For a complete implementation take a look at the example given in the [AsyncSystem](/activejs/fundamentals/systems/asyncsystem).

You can find even more examples in the [Examples](/activejs/more/examples) section.


# React

Using ActiveJS with React is pretty straightforward since ActiveJS has the same basic API as every other subscription-based State Management solution. If you're following the [general guidelines](/activejs/guides/code-style), then you are already on the right path.

Apart from the following examples, you will find more examples in the [Examples](/activejs/more/examples) section.

## Examples:

### 1. Counter using Hooks

Here's an example of implementing a simple **counter** with ActiveJS [NumUnit](/activejs/fundamentals/units/numunit) and **React Hooks**.

```typescript
// initialize a NumUnit.
const counterUnit = new NumUnit() // with default value 0

// define two pure functions that produce a new value
const increment = value => value + 1;
const decrement = value => value - 1;

// create a react component
function App() {
  const [value, setValue] = useState<number>(); // create local state

  // use an effect to update the local state when counterUnit's value changes
  useEffect(() => {
    const subscription = counterUnit.subscribe(setValue);
    return () => subscription.unsubscribe(); // prevent memory leak
  }, []);

  return (
    <React.Fragment>
      Counter Value: {value}

      <button onClick={() => counterUnit.dispatch(increment)}>Increase</button>
      <button onClick={() => counterUnit.dispatch(decrement)}>Decrease</button>
    </React.Fragment>
  );
}
```

Try it out on [StackBlitz](https://stackblitz.com/edit/react-ts-deakuh?file=index.tsx).

### 2. Counter using [useUnit](/activejs/integrations/react/useunit-hook) Hook

Here's the same **counter** example using the [useUnit](/activejs/integrations/react/useunit-hook) Hook. This is much better than replicating the same `useState` and `useEffect` logic every time you want to use a Unit.

```typescript
// initialize a NumUnit.
const counterUnit = new NumUnit() // with default value 0

// define two pure functions that produce a new value
const increment = value => value + 1
const decrement = value => value - 1

// create a react component
function App() {
  const {value, dispatch, resetValue} = useUnit(counterUnit)

  return (
    <React.Fragment>
      Counter Value: {value}

      <button onClick={() => dispatch(increment)}>Increase</button>
      <button onClick={() => dispatch(decrement)}>Decrease</button>
      <button onClick={() => resetValue()}>Reset</button>
    </React.Fragment>
  )
}
```

Try it out on [StackBlitz](https://stackblitz.com/edit/react-ts-bf5mxu?file=index.tsx).

### 3. Counter using [useObservable](/activejs/integrations/react/useobservable-hook) Hook

Here's the same **counter** example again, using the [useObservable](/activejs/integrations/react/useobservable-hook) Hook. This is even better than [useUnit](/activejs/integrations/react/useunit-hook), since we don't have to re-map the Unit's API again in a Hook, we just need the dynamic value to trigger rendering update, and for `dispatch` and other methods, we can use the Unit directly.

```typescript
// initialize a NumUnit.
const counterUnit = new NumUnit() // with default value 0

// define two pure functions that produce a new value
const increment = value => value + 1;
const decrement = value => value - 1;

// create a react component
function App() {
  const value = useObservable(counterUnit);

  return (
    <React.Fragment>
      <p>
        Counter Value: <b>{value}</b>
      </p>

      <button onClick={() => counterUnit.dispatch(increment)}>Increase</button>
      <button onClick={() => counterUnit.dispatch(decrement)}>Decrease</button>
      <button onClick={() => counterUnit.resetValue()}>Reset</button>
    </React.Fragment>
  );
}
```

Try it out on [StackBlitz](https://stackblitz.com/edit/react-ts-iifk5z?file=index.tsx).


# useObservable Hook

Since all the fundamental constructs like Units, Actions, Systems, and Clusters are Observable, it makes sense that we create a custom Hook to easily bind their value to a component's local state. `useObservable` is much simpler and ergonomic to use than [useUnit](/activejs/integrations/react/useunit-hook).&#x20;

### useObservable Hook:

{% tabs %}
{% tab title="TypeScript" %}

```typescript
import { useState, useEffect } from "react";
import { Observable } from "rxjs";

export type ObservableValueType<T> = T extends Observable<infer X> ? X : never;

export function useObservable<U extends Observable<any>>($: U) {
  type T = ObservableValueType<U>;
  const [value, setValue] = useState<T>();

  useEffect(() => {
    const subscription = $.subscribe(setValue);
    return () => subscription.unsubscribe();
  }, [$]);

  return value;
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
import { useState, useEffect } from "react";
import { Observable } from "rxjs";

export function useObservable(observable) {
  const [value, setValue] = useState();

  useEffect(() => {
    const subscription = observable.subscribe(setValue);
    return () => subscription.unsubscribe();
  }, [observable]);

  return value;
}
```

{% endtab %}
{% endtabs %}

### Example:

```typescript
// create a Unit or System, Cluster, Action
const listUnit = new ListUnit({initialValue: ['🤯']});

// a simple component
function Visualizer() {
  const value = useObservable(listUnit);

  return <span>{value}</span>;
}

// it'll render this immediately and will render any future values
🤯
```

### More Examples:

* [StackBlitz](https://stackblitz.com/edit/react-ts-aj1f8t?file=index.tsx) example that shares a Unit among multiple components.
* Simple [Counter](https://docs.activejs.dev/integrations/react#3-counter-using-useobservable-hook) example.
* See [this](https://docs.activejs.dev/fundamentals/systems/asyncsystem#react) for usage in combination with [AsyncSystem](/activejs/fundamentals/systems/asyncsystem).


# useUnit Hook

Using the ActiveJS is similar to RxJS Observables and other observable and subscription-based libraries.

However, if you don't want to create a `useState` and `useEffect` binding every time you use a Unit, you can create a custom `Hook` for using ActiveJS [Units](/activejs/fundamentals/units), and pass the Unit to `useUnit` Hook to bind the Unit with your React component.

### useUnit Hook:

{% tabs %}
{% tab title="TypeScript" %}

```typescript
import { useState, useEffect } from "react";
import { UnitBase } from "@activejs/core";

const bind = <T extends Function>(method: T, thisArg: any): T =>
  method.bind(thisArg)

export type UnitValueType<T> = T extends UnitBase<infer X> ? X : never

export function useUnit<U extends UnitBase<any>>(unit: U) {
  type T = UnitValueType<U>
  const [value, setValue] = useState<T>()

  useEffect(() => {
    const subscription = unit.subscribe(setValue);
    return () => subscription.unsubscribe();
  }, [])

  return {
    value,
    dispatch: bind(unit.dispatch, unit),
    resetValue: bind(unit.resetValue, unit)
  }
}
```

{% endtab %}

{% tab title="JavaScript" %}

```javascript
import { useState, useEffect } from 'react'
import { UnitBase } from '@activejs/core'

export const useUnit = (unit) => {
  const [value, setValue] = useState()

  useEffect(() => {
    const subscription = unit.subscribe(setValue)
    return () => subscription.unsubscribe()
  }, []);

  const dispatch = v => unit.dispatch(v)
  const resetValue = () => unit.resetValue()

  return {value, dispatch, resetValue}
}
```

{% endtab %}
{% endtabs %}

### Examples:

* See [this](https://docs.activejs.dev/integrations/react#2-counter-using-useunit-hook) for basic usage.


# Configuration

ActiveJS tries to give as many configuration options as possible to allow some degree of customization and personalization. While not requiring any configuration by choosing the most sensible defaults.

Configuration can be done on many levels, it can be done per instance and it can also be done globally.

## Inline / per-instance configuration

```typescript
// Unit configuration
const aUnit = new GenericUnit({cacheSize: 10, immutable: true, persistent: true})

// Action configuration
const anAction = new Action({initialValue: 'START'})

// AsyncSystem configuration
const anAsyncSystem = new AsyncSystem({
    freezeQueryWhilePending: true,
    
    // it overrides AsyncSystem's member Units' config
    // it applies to all three GenericUnits and one BoolUnit
    UNITS: {cacheSize: 3},
    
    // it overrides common UNITS config above, applies to dataUnit only
    DATA_UNIT: {cacheSize: 4}
})
```

## Global configuration

ActiveJS exposes a global class called [Configuration](https://api.activejs.dev/classes/configuration), through which you can set and reset global config that overrides default configuration. Which can still be overridden by inline config.

To set the global config you can use the `set` method, it accepts a configuration object of type [GlobalConfig](https://api.activejs.dev/interfaces/globalconfig).

```typescript
Configuration.set({
    // it overrides default Action config
    ACTION: {replay: true},
    
    // it overrides default Unit config, for all Unit types
    UNITS: {cacheSize: 1},
    
    // it overrides global UNITS config above, for GenericUnits
    GENERIC_UNIT: {cacheSize: 2},
    
    ASYNC_SYSTEM: {
        // it overrides global UNITS, GENERIC_UNIT, and BOOL_UNIT config
        // it applies to AsyncSystem's three GenericUnits and one BoolUnit
        UNITS: {cacheSize: 3},
        
        // it overrides global ASYNC_SYSTEM.UNITS config above, for dataUnit
        DATA_UNIT: {cacheSize: 4}
    }
});
```

## Hierarchy of configuration

The more specific a configuration the higher precedence it has.

Given the global config type interface [GlobalConfig](https://api.activejs.dev/interfaces/globalconfig).\
This is how the precedence order works, going from lowest to highest precedence.

| Units                                                                                                                                                                                        | AsyncSystem                      | Action                    | Cluster                    |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------- | ------------------------- | -------------------------- |
| **Default config**                                                                                                                                                                           | **Default config**               | **Default config**        | **Default config**         |
| GlobalConfig > **UNITS**                                                                                                                                                                     | GlobalConfig > **ASYNC\_SYSTEM** | GlobalConfig > **ACTION** | GlobalConfig > **CLUSTER** |
| <p>Type-specific Unit config e.g.</p><p>GlobalConfig > <strong>DICT\_UNIT</strong></p>                                                                                                       | **Inline config**                | **Inline config**         | **Inline config**          |
| GlobalConfig > ASYNC\_SYSTEM > **UNITS**                                                                                                                                                     |                                  |                           |                            |
| <p>Unit specific config e.g.</p><p>GlobalConfig > ASYNC\_SYSTEM > UNITS > <strong>DATA\_UNIT</strong></p><p>or</p><p>GlobalConfig > ASYNC\_SYSTEM > UNITS > <strong>QUERY\_UNIT</strong></p> |                                  |                           |                            |
| **Inline config**                                                                                                                                                                            |                                  |                           |                            |

## Notes

* In a Single Page App, you should set global configuration only once, and override it in the inline config if needed. Otherwise, it can become very difficult to keep track of which instances are using what configuration, depending on their time of creation.
* If you do need to change global configuration multiple times, just keep in mind that calling `Configuration.set` second time doesn't merge the new configuration with the old one it simply rewrites it. However, the defaults are not affected by this behavior, they have to be overridden specifically every time.


# Nesting

As we know, ActiveJS doesn't have a single store, it has **storage** [Units](/activejs/fundamentals/units), hence instead of creating slices, we create groups.

When you need to combine multiple storage Units (or even other ActiveJS constructs) you can do that using the [Cluster](/activejs/fundamentals/cluster), to build a nested data structure, instead of storing deeply nested values in the Units.

### Combining Multiple Units to create a Meaningful Cluster

To do proper nesting and to make sure that you use ActiveJS Units as intended, you should try to keep the values of the Units flat, *i.e.: as less nested as possible.*

This would allow you to have clear and granular control over the state of your App. Updating and accessing the stored values would be much easier and efficient as well. For example:

```typescript
// instead of doing this
const store = new DictUnit({initialValue: {
  token: 'auth-token',
  userProfile: {...},
  userPreferences: {...}
}})

// do this
const tokenUnit = new StringUnit({initialValue: 'auth-token'})
const userProfileUnit = new DictUnit({initialValue: {...}})
const userPreferencesUnit = new DictUnit({initialValue: {...}})

const userDataCluster = new Cluster({
  tokenUnit, userProfileUnit, userPreferencesUnit // using shorthand notation
})
```

### Accessing and Observing not so nested values of the Unit

Even if you followed the above advice and kept your Units flat you might still want to create an even finer chunk of the information. For that purpose, you can create a [Selection](/activejs/utilities/selection) from a Unit's value.


# Events

Every fundamental ActiveJS construct has a number of built-in Observable events. You can listen to these events by subscribing to the `events$` Observable, a property of every fundamental construct.

[Units](/activejs/fundamentals/units), [Systems](/activejs/fundamentals/systems), [Action](/activejs/fundamentals/action), and [Cluster](/activejs/fundamentals/cluster) have a common `EventReplay` event, it is triggered on a successful manual replay when you call the `replay()` method.

[Units](/activejs/fundamentals/units) have many Units specific events that let you tap into all the action that's happening on a Unit.\
Every Unit has some common events like `EventUnitDispatch`, `EventUnitDispatchFail` and`EventUnitFreeze` etc.

[ListUnit](/activejs/fundamentals/units/listunit) and [DictUnit](/activejs/fundamentals/units/dictunit) have even more events specific to them, like `EventDictUnitSet`, `EventListUnitPush` or `EventListUnitPop` etc.

See [API reference](https://api.activejs.dev/index.html#baseevents) for more details.

## Listening to events

```typescript
const theAction = new Action(); // can also be a Unit, System or Cluster

theAction.events$.subscribe(event => {
    // Action, AsyncSystem and Cluster only have one event
    // so filtering is optional
    if(event instanceof EventReplay) {
        console.log('hey, you got replayed');
    }
});

// dispatch a value
theAction.dispatch('order order');
// this won't trigger any event, only Units emit an event on dispatch 

// replay the value
theAction.replay(); // it'll trigger the EventReplay event
```


# Typings

ActiveJS is strictly typed, it does its best to infer and enforce as many typings as possible. \
However, where it can't infer a type, it uses generics so that you can pass a type.

For example, [Units](/activejs/fundamentals/units), [Systems](/activejs/fundamentals/systems), and [Action](/activejs/fundamentals/action) accept a type for their value.\
[Cluster](/activejs/fundamentals/cluster) doesn't need to be passed types, as it can infer the types from the provided members automatically.

## Units

[BoolUnit](/activejs/fundamentals/units/boolunit), [NumUnit](/activejs/fundamentals/units/numunit), and [StringUnit](/activejs/fundamentals/units/stringunit) don't accept a type because it's already implied as `boolean`, `number`, and `string`, respectively.

[ListUnit](/activejs/fundamentals/units/listunit)'s value already has an `array` type, but it can't know about the type of items that the array is going to contain. You can pass it at the time of instantiation.

```typescript
// a ListUnit whose value type would be string[]
const namesList = new ListUnit<string>();

namesList.push('Mr. Anderson'); // works
namesList.dispatch(['Trinity', 'Morpheus']) // works

namesList.push(737); // linting error, invalid value
namesList.dispatch([737]) // linting error, invalid value
```

[DictUnit](/activejs/fundamentals/units/dictunit)'s value already has an `object` literal type, but it doesn't know the type of key-value pairs it's going to hold. You can pass it at the time of instantiation.

```typescript
// a DictUnit whose value type would be {[key in 'a' | 'b' | 'c']: number}
const someDict = new DictUnit<{[key in 'a' | 'b' | 'c']: number}>();

someDict.set('a', 1993) // works
someDict.dispatch({a: 1, b: 2, c: 3}) // works

someDict.set('b', 'not a number') // linting error, invalid value
someDict.set('d', 1993) // linting error, invalid key
someDict.dispatch({a: 1, b: 2}) // linting error, property 'c' is missing
```

[GenericUnit](/activejs/fundamentals/units/dictunit)'s value has an `any` type, it allows all types of values and leaves the typings to the developer. You can pass it at the time of instantiation.

```typescript
// a GenericUnit whose value type would be string | number | boolean
const primitivesUnit = new GenericUnit<string | number | boolean>();

primitivesUnit.dispatch(42); // works
primitivesUnit.dispatch('HanuMan'); // works
primitivesUnit.dispatch(true); // works

primitivesUnit.dispatch(['you and I']) // linting error, invalid value
primitivesUnit.dispatch({youAreMine: true}) // linting error, invalid value
```

## Systems

[AsyncSystem](/activejs/fundamentals/systems/asyncsystem) doesn't have a value of its own, it derives value from its member Units, 3 of them are GenericUnits and 1 is BoolUnit. The three GenericUnits can be supplied types through AsyncSystem's generics.

```typescript
type UserQuery = number; // type for queryUnit's value
type UserData = string; // type for dataUnit's value
type UserError = {status: number, message: string}; // type for errorUnit's value

// pass the types to AsyncSystem
const userSystem = new AsyncSystem<UserQuery, UserData, UserError>();

userSystem.queryUnit.dispatch(666) // works
userSystem.dataUnit.dispatch('evil string') // works
userSystem.errorUnit.dispatch({status: 418, message: "I'm a teapot"}) // works

userSystem.queryUnit.dispatch('not a number') // linting error, invalid value
userSystem.dataUnit.dispatch(420) // linting error, invalid value
userSystem.errorUnit.dispatch("I'm a teapot") // linting error, invalid value
```

[Custom AsyncSystem](/activejs/fundamentals/systems/custom-asyncsystem) doesn't need to be passed types explicitly, since it doesn't create Units itself, they are provided externally, and it can infer the types from the provided Units.

## Action

[Action](/activejs/fundamentals/action) has `any` as its default value type, it can be restricted by passing a specific type through generics.

```typescript
// an Action that will allow strings
const heroAction = new Action<string>();

heroAction.dispatch('fight injustice') // works
heroAction.dispatch('defeat bullies') // works

heroAction.dispatch(['catch', 22]) // liniting error, invalid value
```


# Caching

By default all ActiveJS [Units](/activejs/fundamentals/units) cache 2 values, and can be configured with minimum `1` or maximum `Infinity` for as many values as possible.

The cache is maintained in an `array`, at the last index we have the latest value, and at 0 index we have the first value. So the cache might look like this `[initialValue, v1, v2, ... , lastDispatchedValue]`. When the length becomes more than the `cacheSize`, values are removed from the start.

The way cache-navigation methods work is that, when you call one of them, let's say `goBack`, the Unit will emit the previous value from the cache, without modifying the cached values, so that the cached values would still be the same and in the same order. Only that the `cacheIndex` would now be `cacheIndex - 1`

Now if you dispatch a new value, this new value will be inserted directly after the current `cacheIndex` and all the values coming after that will be removed from the cache. So that the new value would become the last value in the cache. That's exactly how browser history works, we can open links after links, then we can go back and we can go forward, but as soon as we open a new link, that link becomes the last point in history, and now we can only go back.

However, if you don't want that to happen you can do an in-place cache replace by passing `{replaceCache: true}` flag to the dispatch method. It'll replace the value in cache at the current `cacheIndex`, just like we'd do `History.replaceState()` in case of browser history.

```typescript
const unit = new StringUnit({initialValue: 'a'}); 

// cache is ['a']

unit.goBack(); // won't work, returns false
unit.goForward(); // won't work, returns false

unit.dispatch('b'); // cache becomes ['a', 'b']
console.log(unit.value()) // logs 'b'

unit.goBack(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'a'

unit.goForward(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'b'

unit.jumoToStart(); // cache is still ['a', 'b']
console.log(unit.value()) // logs 'a'

unit.dispatch('d', {replaceCache: true}) // now the cache becomes ['d', 'b']
// 'a' is gone, instead of 'b'
console.log(unit.value()) // logs 'd'

unit.jump(1) // cache is still ['d', 'b']
console.log(unit.value()) // logs 'b'

// we can also access all the cached values
console.log(unit.cachedValues()) // logs ['d', 'b']

// or check the current cache index
console.log(unit.cacheIndex) // logs 0

// or check the count of cached values
console.log(unit.cachedValuesCount) // logs 2
```

## Cache navigation and immutability

When you use cache navigation with Units that store non-primitive values i.e. [DictUnit](/activejs/fundamentals/units/dictunit), [ListUnit](/activejs/fundamentals/units/listunit), and [GenericUnit](/activejs/fundamentals/units/genericunit), you will need to make sure to not mutate the value, otherwise cached value will also get mutated and `goBack`, `goForward` or other cache-navigation methods wouldn't work as expected, because the cached values would have been mutated, which is not what you expect.

To mitigate this problem you can simply make the Unit immutable, which will ensure that the cached values stay unaffected. See [Immutability](/activejs/guides/immutability) for how immutability works in ActiveJS Units.

Otherwise, you have to ensure that every time you dispatch a value it shouldn't have any reference to the Unit's current value, and when you access the Unit's value, you should make sure to not mutate this value in any way.


# Persistence

ActiveJS [Units](/activejs/fundamentals/units) can be made persistent by setting a configuration flag to `true`. By default, persistent Units use [`localStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage) for the persistence. You can change it to any storage API that implements [`Storage`](https://developer.mozilla.org/en-US/docs/Web/API/Storage) interface. e.g.: [`sessionStorage`](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)

## Creating a persistent Unit

All that it takes to make a Unit persistent is a flag, and a unique `id`. The `id` is required to identify the Unit and its stored value.

```typescript
// this will throw an error, id is required
const preferencesUnit = new DictUnit({persistent: true});

// this will work
const preferencesUnit = new DictUnit({id: 'preferences', persistent: true});


// update Unit's value
preferencesUnit.set('side', 'dark');
// value in the LocalStorage would become {"side": "dark"}

// refresh the browser window

// check value
console.log(preferencesUnit.value()) // logs {"side": "dark"}
```

Voila! we're done. No manual saving, no manual retrieving.

## Initial value vs persisted value

When you provide an initial value to a persistent Unit, at first instance it gets saved to the persistent storage immediately, but when you refresh the browser window or open a new one, on the second instance the stored value takes precedence over the provided initial value.

```typescript
const preferencesUnit = new DictUnit({
    id: 'preferences', 
    persistent: true,
    initialValue: {earth: 'flat'}
});
// value in the LocalStorage would become {"earth": "flat"}

// set a new preference, which dispatches and saves a new value
preferencesUnit.set('earth', 'oblate ellipsoid');
// now LocalStorage has {"earth": "oblate ellipsoid"}

// now, refresh the browser window

// check value
console.log(preferencesUnit.value()) // logs {"earth": "oblate ellipsoid"}
// the initial value gets ignored
```

## Clearing the persisted value

Persisted value can be cleared in two ways, per Unit, or every Unit in a Storage instance.

* To clear the persisted value of a Unit, you can use `Unit.clearPersistedValue()`
* To clear all Units' persisted values from the default storage, you can use the global function `clearPersistentStorage()`.
* If you want to clear a particular storage you can pass it to the `clearPersistentStorage()` function.\
  **e.g**. `clearPersistentStorage(window.sessionStorage)`&#x20;

```typescript
// taking the Unit from above example, and starting from where we left
console.log(preferencesUnit.value()) // logs {"earth": "oblate ellipsoid"}

// clear the persisted value
preferencesUnit.clearPersistedValue();
// or clearPersistentStorage()
// or clearPersistentStorage(localStorage)

// check value
console.log(preferencesUnit.value()) // logs {"earth": "oblate ellipsoid"}
// because only the persisted value is removed, the Unit's value stays intact

// now, refresh the browser window

// check value
console.log(preferencesUnit.value()) // logs {"earth": "flat"}
// the initial value is used, because we cleared the persisted value
```

## Changing the persistence storage

All Units use the `localStorage` for persistence by default, but it can be changed to `sessionStorage` as well, and you can either change it globally or for a specific Unit.

### Changing storage for one Unit

```typescript
const unit = new DictUnit({
    id: 'session-token', 
    persistent: true, 
    
    // this is how we can change the storage for a Unit
    storage: window.sessionStorage
    // it overrides the default/global storage configuration
});
```

### Changing default storage for every Unit

You can change the default Storage API used by ActiveJS Units through the global [Configuration](/activejs/guides/configuration).

```typescript
// set it in global configuration
Configuration.set({storage: window.sessionStorage})
// now all the persistent Units will use SessionStorage
// and the global clearPersistentStorage() will also operate on SessionStorage
```

{% hint style="danger" %}
Be advised that you should only change it once and that too before initializing any persistent Unit.\
Otherwise, some persistent Units will save their values in `LocalStorage` and try to restore it from `SessionStorage`. Also, the global function`clearPersistentStorage()` won't be able to clear persisted values from the other storage, you'll have to manually provide the non-current storage you want to clean up.
{% endhint %}

## Supported data types

It's advised to put only serializable data types in a persistent Unit, otherwise, the information will be lost in serialization done to save it in the LocalStorage. Non-serializable data types like Date, Map, Set, etc. are not supported.

All the data types that support `JSON.stringify` and `JSON.parse` can be used as values.

**Note:** `Date` object works with `JSON.stringify`, however it can't be parsed back to a `Date` object.\
When using the persisted value of the Unit, you'll only get a `string` representation of `Date`, not a `Date` `object`.


# Immutability

ActiveJS [Units](/activejs/fundamentals/units) that store primitive values i.e. [BoolUnit](/activejs/fundamentals/units/boolunit), [NumUnit](/activejs/fundamentals/units/numunit), and [StringUnit](/activejs/fundamentals/units/stringunit) are automatically immutable because these Units deal with primitive values, and primitive values in JavaScript are immutable.

The [Units](/activejs/fundamentals/units) that store non-primitive values i.e. [DictUnit](/activejs/fundamentals/units/dictunit), [ListUnit](/activejs/fundamentals/units/listunit), and [GenericUnit](/activejs/fundamentals/units/genericunit) can be made immutable by just setting a configuration flag to `true`.

## Creating an immutable Unit

```typescript
const immutableDict = new DictUnit({immutable: true});
// we're done, it's immutable now
```

## Making all Units immutable

All the Units can be made immutable by default, by setting a flag in the global configuration.

```typescript
Configuration.set({
    UNITS: {immutable: true}
});
// all the Units initialized after this will be immutable,
// if not configured otherwise

const immutableList = new ListUnit(); // immutable

// override global config
const mutableList = new ListUnit({immutable: false}); // mutable
```

## Efficiency and precautions

Immutability brings a lot of benefits, such as predictability, and improving JS frameworks' rendering performance by avoiding the need for dirty checking, etc.

However, if not used correctly, there is a chance that you might run into performance bottlenecks.

Although ActiveJS takes most of these precautions on your behalf and tries to give the best experience and performance without any significant change in development practices and flow. There are still a few things that you might want to be aware of.

**When a Unit is immutable:**

1. Avoid using the static value access as much as you can, since the `value()` method creates a new copy every time you call it. Instead use Observable value, which is shared with all the observers.
2. Don't use the `value()` method directly in an Angular template, otherwise on every change detection there will be a new copy. Instead use the Units with `async` pipe.
3. Prefer using [ListUnit](/activejs/fundamentals/units/listunit) and [DictUnit](/activejs/fundamentals/units/dictunit) over [GenericUnit](/activejs/fundamentals/units/genericunit), and use methods like `set`, `get`, `findByProp`, etc. that do not create a copy on their invocation.
4. When dispatching a value using the `dispatch` method, you can mutate the value provided to the value-producer function, because it's a copy. And if you don't intend to use the current value to create a new value, just pass the new value directly so that the Unit doesn't waste a copy.
5. When you need to invoke a method like `find` which uses a predicate method to loop over stored items, if you can ensure that you won't mutate the value, you can invoke these methods on raw value instead, without creating a copy by using `Unit.rawValue()` e.g:`ListUnit.rawValue().find(item => item.name.startsWith('A'))`

In general, just try to avoid methods that create a new copy, and use alternative methods that do not. You can check this information in the documentation available within the library, or you can refer to [API reference](https://api.activejs.dev).

## Supported data types

It's advised to put only serializable data types in an immutable Unit, non-serializable data types like Map, Set, etc. are not cloned by ActiveJS. They will be left as is and will be shared by reference (i.e. will be mutable).

All the primitive data types like `boolean`, `number`, etc. are supported by default, along with `array` and simple `object` that can be cloned by ActiveJS, and hence can be guaranteed to be immutable.


# Freeze and Mute

Every ActiveJS [Unit](/activejs/fundamentals/units) comes with built-in capability to get frozen and muted, to stop the new data from getting dispatched, and to stop emitting any new data being dispatched, respectively.

In simple terms, freezing a Unit stops any incoming changes towards it, and muting the Unit stops any outgoing changes or events.

To understand it better let's look at them separately:

## Freeze / Unfreeze

If you know about [Object.freeze](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze), then that's not what it is, but the end result is almost the same and the rationale is also very similar.

```typescript
const unit = new ListUnit(); // or any other Unit

// freeze
unit.freeze();

unit.dispatch([1, 2]); // would not work

// unfreeze
unit.unfreeze();

unit.dispatch([1, 2]); // would work
```

To freeze a Unit you just have to call `Unit.freeze()`  and the Unit would stop responding to any call to `dispatch` method or any other method that will cause the Unit's value to change or make the Unit emit a value. This behavior can be useful when you're waiting for an event or task to complete and don't want the Unit to accept any values in that period, e.g.: when a form is being submitted.

When a Unit is frozen the following write-operations stop working:

* **All Units**: `dispatch`, `replay`, `goBack`, `goForward`, `jump`; and any other method that will cause the value to change or be emitted.
* **ListUnit:** `push`, `pop`, `set`, `splice`, `sort`, `reverse`; and any other method that will cause the value to change.
* **DictUnit:** `set`, `assign`, `delete`; and any other method that will cause the value to change.

But all the read-operations will keep working as usual, such as:

* **All Units:** accessing the `value`, `subscribing` to the Unit; or any other read-only operation
* **ListUnit:** methods such as `get`, `find`, `includes`, `slice`; or any other read-only operation
* **DictUnit:** methods such as `get`, `has`; or any other read-only operation

## Mute / Unmute

Muting a Unit is similar to muting a chat group in an instant messaging app, the conversation might still be ongoing it's just that you're not being notified anymore.

Similarly, when a Unit is muted, it still allows all the mutations and write operations as usual, unlike **freeze.** But it stops broadcasting those changes, what it means is that subscribers won't be notified if the value got changed or replayed. It also stops emitting events.

You can use this feature to disconnect a Unit from e.g.: triggering rendering updates or any other linked task, while still keeping the Unit up to date with any new data being dispatched to it, so that you can reconnect it later without losing any data updates.

```typescript
const unit = new ListUnit(); // or any other Unit

// mute
unit.mute();

// unmute
unit.unmute();
```

When a Unit is muted:

* Subscribing to the Unit will still provide an immediate value, but it'll be the value that was emitted just before the Unit got muted. Moreover, no new values will be provided until the Unit becomes unmuted.
* `createStream` will create a Stream but it'll do the same thing as above, only one value will be provided.
* Subscribing to the events will work but there won't be any events until the Unit becomes unmuted.
* `emitCount` will not change.

When a Unit gets unmuted after being muted:

* If the value changed while the Unit was muted, then on calling unmute, the latest value will be broadcasted immediately, to bring all the subscribers in sync with the Unit.
* If there was no change in value, there won't be an immediate emission.


# Development Environment

To help with development, and prevent some sneaky bugs that can be hard to debug, ActiveJS provides a few checks that you can enable in a development environment. You can configure them like this.

```typescript
Configuration.set({
    checkUniqueId: true, // default is false
    checkImmutability: true, // default is false
    checkSerializability: true // default is false
})
```

ActiveJS provides the following checks:

* **`checkImmutability`** Enables immutability violation checks for all the ActiveJS constructs, it blocks any attempts of state mutation and throws an error with information about where the violation occurred.
* **`checkUniqueId`** Enables unique id checks across all the ActiveJS constructs, such that if any of the two ActiveJS instances have the same id, it'll throw an error.
* **`checkSerializability`** Enables serializability checks for Units and Actions, it'll throw an error if a non-serializable value is passed to an Action or Unit.

See [API reference](https://api.activejs.dev/interfaces/environmentconfig) for more details.

### Notes

* You should only use these checks in a development environment to avoid causing unwarranted errors in a production deployment.
* To automate this process you can use an environment variable provided by the framework of your choice, that identifies the development environment, and enable ActiveJS' production mode to disable all the checks.\
  e.g.: in Angular it'd look like this

  ```typescript
  // in the app.module.ts

  if (environment.production) {
    Configuration.enableProdMode();
  }
  ```


# General Guidelines

ActiveJS doesn't concern itself with how or where it gets used, it's intended to be immersed in your development workflow and practices. It's just an improvement over already existing native data structures, and more powerful than a simple Observable or Subject.

The whole point of ActiveJS is to provide a non-intrusive and non-disruptive State Management solution that just fits in, without drawing too much attention to itself.

However, for the sake of having an official guideline, and to avoid some problems that we've identified, which you might run into at some point, you can follow this guideline.

## Don't mutate the state

To get predictable and reliable [cache navigation](/activejs/guides/caching), otherwise, you would get unexpected results.

To avoid view-rendering problems in your framework of choice. You might be expecting your framework to detect a change and render it, but since you mutated the value, the framework can't know whether there's a change or not.

To make things more predictable in general, since you can be sure that once you dispatch a value to a Unit, it's not going to change until you dispatch a new value again. Which can help avoid a lot of bugs.

{% hint style="info" %}
A simple solution to avoid mutating the state is to make your Units immutable. See [Immutability](/activejs/guides/immutability).
{% endhint %}

## Don't put non-serializable values in Units

For [persistent](/activejs/guides/persistence) Units, you should always make sure that the value of the Unit is serializable, otherwise, the information will be lost in serialization, which is done for storing the value into LocalStorage.

ActiveJS Units can only clone simple serializable objects, so if you're relying on [immutable](/activejs/guides/immutability) Units to provide a clone, that won't happen for non-serializable objects.

It's generally a good idea to not use non-serializable objects like Date, Map, Set, DOM-Element, etc. in your state for predictability and simplicity. However, if you are not using persistence, immutability or cache-navigation, in rare cases it's probably okay to do so, and ActiveJS shouldn't have a problem with it.

## Keep shared things in a separate file

To avoid cyclic dependencies while still having the freedom to pull in data from different files and services, you must put the shared [Units](/activejs/fundamentals/units), [Actions](/activejs/fundamentals/action), [Streams](/activejs/utilities/stream), [Systems](/activejs/fundamentals/systems), or [Clusters](/activejs/fundamentals/cluster) in a dedicated, shared file or service.

Keeping the [Streams](/activejs/utilities/stream) in a separate file alone will help avoid most of the possibilities of having a cyclic dependency. Since the Streams tend to interact with a lot of other instances of Units, Action, or Systems; keeping them in separate files will ensure that you don't import something into a file that has a Stream, which is importing something from the said file.

Try to keep the related [Units](/activejs/fundamentals/units), [Actions](/activejs/fundamentals/action), [Systems](/activejs/fundamentals/systems), or [Clusters](/activejs/fundamentals/cluster) as close as possible, to avoid fragmentation that's hard to keep track of. Keep the related [Streams](/activejs/utilities/stream) together as well, but as pointed out earlier, try to keep them away from [Units](/activejs/fundamentals/units), [Actions](/activejs/fundamentals/action), [Systems](/activejs/fundamentals/systems), or [Clusters](/activejs/fundamentals/cluster).

## Keep the streams simple

[Streams](/activejs/utilities/stream) are supposed to make complex things easy, but if a Stream starts to have too many dependencies or unrelated side-effects embedded into it, then it has the potential of making the Streams incomprehensible and hard to debug.

When you create a Stream on [AsyncSystem](/activejs/fundamentals/systems/asyncsystem) to populate its data, you should try to not have other unrelated side-effects in that Stream, try to keep it as simple as possible.  If you need to have side-effects, you can create new Streams on [AsyncSystem](/activejs/fundamentals/systems/asyncsystem)'s Units e.g.: `dataUnit`, `errorUnit`


# Examples

1. [Counter (Vanilla JS)](https://stackblitz.com/edit/rxjs-daesrs?file=index.ts)
2. [Counter (React Hooks)](https://stackblitz.com/edit/react-ts-deakuh?file=index.tsx)
3. [Counter (React + useUnit Hook)](https://stackblitz.com/edit/react-ts-bf5mxu?file=index.tsx)
4. [TodoMVC (Angular)](https://activejs.dev/#/examples/todomvc)
5. [Typeahead (Angular)](https://activejs.dev/#/examples/typeahead)
6. [Typeahead (React + RxJS)](https://stackblitz.com/edit/react-ts-spn9ze?file=index.tsx)
7. [Typeahead (RxJS)](https://stackblitz.com/edit/typescript-r6zjrg?file=index.ts)
8. [Shared State (React)](https://stackblitz.com/edit/react-ts-aj1f8t?file=index.tsx)


# Articles

{% embed url="<https://dev.to/dabalyan/state-management-with-a-single-line-of-code-2llg>" %}

{% embed url="<https://dev.to/dabalyan/state-management-without-reducers-48km>" %}

{% embed url="<https://dev.to/dabalyan/asynchronous-state-management-with-a-single-line-of-code-2999>" %}


