# 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](https://docs.activejs.dev/activejs/fundamentals/units), [Systems](https://docs.activejs.dev/activejs/fundamentals/systems) and [Clusters](https://docs.activejs.dev/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](https://docs.activejs.dev/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](https://docs.activejs.dev/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](https://docs.activejs.dev/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](https://docs.activejs.dev/activejs/guides/configuration) for more details.
