# NGXS

<div align="left"><figure><picture><source srcset="/files/ionyiA45XgbsACMI8huj" media="(prefers-color-scheme: dark)"><img src="/files/h6PW0SQebRYekf6QDjVM" alt="" width="250"></picture><figcaption></figcaption></figure></div>

[![Discord](https://img.shields.io/discord/1008573955587702894?style=flat-square\&logo=discord\&label=discord\&link=https%3A%2F%2Fdiscord.com%2Fchannels%2F1008573955587702894)](https://discord.com/channels/1008573955587702894) [![](https://badge.fury.io/js/%40ngxs%2Fstore.svg)](https://badge.fury.io/js/%40ngxs%2Fstore) [![](https://api.codeclimate.com/v1/badges/5b43106a1ddff7d76a04/maintainability)](https://codeclimate.com/github/ngxs/store/maintainability) [![](https://api.codeclimate.com/v1/badges/5b43106a1ddff7d76a04/test_coverage)](https://codeclimate.com/github/ngxs/store/test_coverage) [![](https://circleci.com/gh/ngxs/store/tree/master.svg?style=svg)](https://circleci.com/gh/ngxs/store)

### ❓ What is NGXS?

NGXS is a state management pattern + library for Angular. It acts as a single source of truth for your application's state, providing simple rules for predictable state mutations.

NGXS is modeled after the CQRS pattern popularly implemented in libraries like Redux and NgRx but reduces boilerplate by using modern TypeScript features such as classes and decorators.

### 👋 New to NGXS?

If you're just getting started with NGXS, I recommend you head over to the [concepts](/readme/intro) and then explore the rich ecosystem of examples in the [community resources](/community-and-labs/community/projects) page.

### ❓ Need Help?

For questions, please ask them on Stack Overflow with the `ngxs` tag: <https://stackoverflow.com/questions/ask?tags=ngxs>

To chat with other users and contributors join us on Discord: <https://discord.gg/yT3Q8cXTnz> (PS. we are migrating from our [Slack](https://join.slack.com/t/ngxs/shared_invite/zt-by26i24h-2CC5~vqwNCiZa~RRibh60Q) server)

If you think there is a bug in this library, you can open an issue on GitHub (<https://github.com/ngxs/store/issues/new>). If possible a link to a [http://stackblitz.com](https://stackblitz.com/edit/ngxs-repro) (or github) repo with a repro or a failing test would be great.

### ❤️ Giving Back

Become a [Contributor](/community-and-labs/community/contributors) or a [Sponsor](/community-and-labs/community/sponsors).

## Sponsors

Thank you to the organisations sponsoring us and to the individuals that financially back our work and the running of our open source community. Become [a sponsor](https://opencollective.com/ngxs#sponsor) or [a backer](https://opencollective.com/ngxs#backer) today. Every bit helps!

### Organisations

[![Organisations](https://opencollective.com/ngxs/sponsors.svg?width=890\&avatarHeight=100)](https://opencollective.com/ngxs#sponsors)

### Individuals

[![Backers](https://opencollective.com/ngxs/backers.svg?width=890)](https://opencollective.com/ngxs#backers)

## Contributors

Thanks to all our [contributors](https://github.com/ngxs/store/graphs/contributors)! Open source does not work without you!

![](https://opencollective.com/ngxs/contributors.svg?width=890)


# Overview

There are 4 major concepts to NGXS:

* Store: Global state container, action dispatcher and selector
* Actions: Class describing the action to take and its associated metadata
* State: Class definition of the state
* Selects: State slice selectors

These concepts create a circular control flow traveling from a component dispatching an action, to a store reacting to the action, back to the component through a state select.

![](/files/-LVrRb1WdI1nngz9VmFm)


# WHY

Why another state management solution? We asked ourselves that same question before we started on NGXS. After trial and error of several different redux based solutions we decided that they didn’t represent the type of API we wanted and expected from Angular.

### Simple

NGXS tries to make things as simple and accessible as possible. There can be a lot of boilerplate code in state management, thus a main goal of NGXS is to reduce boilerplate allowing you to do more things with less. It is also not necessary to be super familiar with RxJs.

RxJs is great and is made use of heavily internally within the project, but the library tries to do as much for you as it can. NGXS drives to let users take advantage of the benefits of Observables but in many cases treat them as an implementation detail of the library rather than a prerequisite.

The other thing that NGXS gets rid of is switch statements. The library is responsible for knowing when functions need to be called.

### Dependency Injection (DI)

A core feature of Angular is dependency injection. It can be a very useful tool and NGXS makes sure that users can use DI in their state management code. This means Angular services can be injected into state classes making it easier to take advantage of more Angular features.

### Action Life Cycles

Actions in NGXS are asynchronous. This allows actions to have a life cycle, meaning we can now listen for when a single action or a collection of actions is complete making complex workflows predictable. It is very common to want to do something after an action is completed and NGXS makes it simple to do.

### Promises

Observables are great but they aren't a silver bullet. Sometimes Promises are the preferred option. NGXS allows either to be returned from an action method.

### Community

NGXS is entirely community built and driven. The project exists to help people build applications and the team is open to any suggestions that help with that goal.


# INSTALLATION

## Installing with schematics

You can install the `@ngxs/store` using `ng-add` schematic

```bash
ng add @ngxs/store
```

Note: This command will prompt you to choose the **plugins** you want to install and the name of the **project** you want to use NGXS with.

You have the option to enter the options yourself

```bash
ng add @ngxs/store --plugins DEVTOOLS,FORM --project angular-ngxs-project
```

| Option    | Description                                               | Default Value               |
| --------- | --------------------------------------------------------- | --------------------------- |
| --project | Name of the project as it is defined in your angular.json | Workspace's default project |
| --plugins | Comma separate the plugins as appear below                |                             |

### Plugins to optionally install using the schematics

* Ngxs developer tools plugin
* Ngxs form plugin
* Ngxs HMR plugin
* Ngxs logger plugin
* Ngxs router plugin
* Ngxs storage plugin
* Ngxs websocket plugin

You can find more information about plugins on the [plugins page](https://www.ngxs.io/plugins).

🪄 **This command will**:

* Update `package.json` dependencies with `@ngxs/store`
* Update `package.json` dependencies with the selected plugins
* Install dependencies by executing `npm install`

If your project is standalone one:

* Update the `providers` array of your selected project with `provideStore([])`

If your application is module based:

* Update the `imports` array of your `app.module.ts` with `NgxsModule.forRoot([])`

## Manual Installation

To get started, install the package from npm. The latest version (3.x) supports Angular/RxJS 6+.

```bash
npm i @ngxs/store

# or if you are using yarn
yarn add @ngxs/store

# or if you are using pnpm
pnpm i @ngxs/store
```

Then, in your `app.config.ts`, add the `provideStore` to the list of providers:

```ts
import { provideStore } from '@ngxs/store';

export const appConfig: ApplicationConfig = {
  providers: [provideStore()]
};
```

When you provide the store at the root level, you can pass root states along with [options](/concepts/store/options). If you are lazy loading, you can use the `provideStates` option with the same arguments.

Options such as `developmentMode` can be passed to the module as the second argument in the `provideStore` function. In development mode, plugin authors can add additional runtime checks/etc to enhance the developer experience. Switching to development mode will also freeze your store using [deep-freeze-strict](https://www.npmjs.com/package/deep-freeze-strict) module.

It's important that you add `provideStore` at the root level even if all of your states are feature states.

## Development Builds

Our continuous integration server runs all tests on every commit to master and if they pass it will publish a new development build to NPM and tag it with the @dev tag.

This means that if you want the bleeding edge of `@ngxs/store` or any of the plugins you can simply do:

```bash
npm install @ngxs/store@dev
npm install @ngxs/logger-plugin@dev
npm install @ngxs/devtools-plugin@dev

# or if you are using yarn
yarn add @ngxs/store@dev
yarn add @ngxs/logger-plugin@dev
yarn add @ngxs/devtools-plugin@dev

# of if you want to update multiple things at the same time
yarn add @ngxs/{store,logger-plugin,devtools-plugin}@dev

# or if you are using pnpm
pnpm install @ngxs/store@dev
pnpm install @ngxs/logger-plugin@dev
pnpm install @ngxs/devtools-plugin@dev
```

This will install the version currently tagged as `@dev`. Your package.json file will be locked to that specific version.

```json
{
  "dependencies": {
    "@ngxs/store": "3.0.0-dev.a0d076d"
  }
}
```

If you later want to again update to the bleeding edge, you will have to run the above command again.


# STARTER KIT

The Starter Kit provides a pre-configured NGXS setup that includes a Store, State, Actions, and selectors.

## Installing with schematics

```bash
ng generate @ngxs/store:starter-kit
```

Note: Running this command will prompt you to create a "Starter-Kit". The options available for the "Starter-Kit" are listed in the table below.

You have the option to enter the options yourself

```bash
ng generate @ngxs/store:starter-kit --path YOUR_PATH
```

| Option    | Description                                                    | Required | Default Value               |
| --------- | -------------------------------------------------------------- | :------: | --------------------------- |
| --path    | The path to create the starter kit                             |    Yes   |                             |
| --spec    | Boolean flag to indicate if a unit test file should be created |    No    | `true`                      |
| --project | Name of the project as it is defined in your angular.json      |    No    | Workspace's default project |

> When working with multiple projects within a workspace, you can explicitly specify the `project` where you want to install the **starter kit**. The schematic will automatically detect whether the provided project is a standalone or not, and it will generate the necessary files accordingly.

🪄 **This command will**:

* Create Auth State, Actions, Selectors and Unit Tests, organized into an 'auth' directory
* Create Dictionary State, Actions, Selectors and Unit Tests, organized into a 'dashboard/states/dictionary' directory
* Create User State, Actions, Selectors and Unit Tests, organized into a 'dashboard/states/user' directory
* Create a Store and Configure the Auth, Dictionary and User states

> Note: The generated files will be organized into a 'store' directory.


# SCHEMATICS

This page lists all the different schematics that can be used to generate NGXS Starter-Kit, Store, Actions and State.

## Starter Kit

The Starter Kit provides a pre-configured NGXS setup that includes a Store, State, Actions, and selectors.

See the [Starter Kit Page](/introduction/starter-kit) to learn more.

## Store

The store is a global state manager that dispatches actions your state containers listen to and provides a way to select data slices out from the global state.

See the [Store Schematics Page](/concepts/store/schematics) to learn more.

## Actions

Actions can either be thought of as a command which should trigger something to happen, or as the resulting event of something that has already happened.

See the [Action Schematics Page](/concepts/actions/schematics) to learn more.

## State

States are classes that define a state container.

See the [State Schematics Page](/concepts/state/schematics) to learn more.


# STORE

The store is a global state manager that dispatches actions your state containers listen to and provides a way to select data slices out from the global state.

### Creating actions

An action example in `animal.actions.ts`.

```ts
export class AddAnimal {
  static readonly type = '[Zoo] Add Animal';

  constructor(public name: string) {}
}
```

### Dispatching actions

To dispatch actions, you need to inject the `Store` service into your component/service and invoke the `dispatch` function with an action or an array of actions you wish to trigger.

```ts
import { Store } from '@ngxs/store';
import { AddAnimal } from './animal.actions';

@Component({ ... })
export class ZooComponent {
  constructor(private store: Store) {}

  addAnimal(name: string) {
    this.store.dispatch(new AddAnimal(name));
  }
}
```

You can also dispatch multiple actions at the same time by passing an array of actions like:

```ts
this.store.dispatch([new AddAnimal('Panda'), new AddAnimal('Zebra')]);
```

Let's say after the action executes you want to clear the form. Our `dispatch` function actually returns an Observable, so we can subscribe to it and reset the form after it was successful.

```ts
import { Store } from '@ngxs/store';
import { AddAnimal } from './animal.actions';

@Component({ ... })
export class ZooComponent {
  constructor(private store: Store) {}

  addAnimal(name: string) {
    this.store.dispatch(new AddAnimal(name)).subscribe(() => this.form.reset());
  }
}
```

The Observable that a dispatch returns has a void type, this is because there can be multiple states that listen to the same `@Action`, therefore it's not realistically possible to return the state from these actions since we don't know the form of them.

If you need to get the state after this, simply use `selectSignal` in the chain like:

```ts
import { Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs';

import { AnimalState } from './animal.state';
import { AddAnimal } from './animal.actions';

@Component({ ... })
export class ZooComponent {
  animals = this.store.selectSignal(AnimalState.getAnimals);

  constructor(private store: Store) {}

  addAnimal(name: string) {
    this.store.dispatch(new AddAnimal(name)).subscribe(() => {
      console.log(this.animals());
      // do something with animals
      this.form.reset();
    });
  }
}
```

#### `dispatch` Utility

NGXS offers a utility function named `dispatch`, which takes an action as a parameter and returns a function. This function can then be called with parameters for the action constructor. When this function is called, the action is created and is dispatched immediately:

```ts
import { dispatch } from '@ngxs/store';

// An action declared somewhere in your app
class Greet {
  static readonly type = 'Greet';

  constructor(public greeting: string) {}
}

// Then, in your component
export class MyComponent {
  greet = dispatch(Greet);

  constructor() {
    // the `this.greet` function has the same signature as the action's constructor!
    this.greet('Hello world!');
  }
}
```

The dispatched function returns a value that is both an `Observable` and a `PromiseLike`, so you can use either reactive or async/await patterns without any API change — the syntax at the call site determines the behavior.

**Reactive (subscribe):**

```ts
export class MyComponent {
  greet = dispatch(Greet);

  onGreet() {
    this.greet('Hello world!').subscribe(() => {
      // action completed
    });
  }
}
```

**Async/await:**

```ts
export class MyComponent {
  greet = dispatch(Greet);

  async onGreet() {
    await this.greet('Hello world!');
    // action completed
  }
}
```

**Error handling with async/await:**

If the action throws, the rejection is propagated into the promise so a standard `try/catch` works as expected:

```ts
export class MyComponent {
  greet = dispatch(Greet);

  async onGreet() {
    try {
      await this.greet('Hello world!');
    } catch (err) {
      // handle error
    }
  }
}
```

### Snapshots

You can get a snapshot of the state by calling `store.snapshot()`. This will return the entire value of the store for that point in time.

### Selecting State

See the [select](/concepts/select) page for details on how to use the store to select data.

### Reset

In certain situations you need the ability to reset the state in its entirety without triggering any actions or life-cycle hooks. One example of this would be redux devtools plugin when we are doing time travel. Another example would be when we are unit testing and need the state to be a specific value for isolated testing.

`store.reset(myNewStateObject)` will reset the entire state to the passed argument without firing any actions or life-cycle events.

Warning: Using this can cause unintended side effects if improperly used and should be used with caution!


# Store Schematics

You can generate the `store` using the command as seen below:

```bash
ng generate @ngxs/store:store
```

Running this command will prompt you to create a "Store" with the options as they are listed in the table below.

Alternatively, you can provide the options yourself.

```bash
ng generate @ngxs/store:store --name NAME_OF_YOUR_STORE
```

| Option    | Description                                                    | Required | Default Value               |
| --------- | -------------------------------------------------------------- | :------: | --------------------------- |
| --name    | The name of the store                                          |    Yes   |                             |
| --path    | The path to create the store                                   |    No    | App's root directory        |
| --spec    | Boolean flag to indicate if a unit test file should be created |    No    | `true`                      |
| --flat    | Boolean flag to indicate if a dir is created                   |    No    | `false`                     |
| --project | Name of the project as it is defined in your angular.json      |    No    | Workspace's default project |

> When working with multiple projects within a workspace, you can explicitly specify the `project` where you want to install the **store**. The schematic will automatically detect whether the provided project is a standalone or not, and it will generate the necessary files accordingly.

> Be sure to update `provideStore` in `app.config.ts` if working with standalone project or `NgxsModule.forRoot([])` in `app.module.ts` if working with module based project. Without this, your app will not recognise your store and actions properly.

🪄 **This command will**:

* Generate a `{name}.actions.ts`
* Generate a `{name}.state.spec.ts`
* Generate a `{name}.state.ts`. The state file also includes an action handler for the generated action.

> Note: If the --flat option is false, the generated files will be organized into a directory named using the kebab case of the --name option. For instance, 'MyStore' will be transformed into 'my-store'.


# Store Options

You can provide an `NgxsModuleOptions` object as the second argument of your `NgxsModule.forRoot` call. The following options are available:

* `developmentMode` - Setting this to `true` will add additional debugging features that are useful for development time. This includes freezing your state and actions to guarantee immutability. (Default value is `false`). It makes sense to use it only during development to ensure there're no state mutations. When building for production, the `Object.freeze` will be tree-shaken away.
* `selectorOptions` - A nested options object for providing a global options setting to be used for selectors. This can be overridden at the class or specific selector method level using the `SelectorOptions` decorator. The following options are available:
  * `suppressErrors` - Setting this to `true` will cause any error within a selector to result in the selector returning `undefined`. Setting this to `false` results in these errors propagating through the stack that triggered the evaluation of the selector that caused the error. (Default value is `false`).
  * `injectContainerState` ([TO BE DEPRECATED](/deprecations/inject-container-state-deprecation)) - Setting this to `true` will inject the container state model as the first parameter of a selector method (defined within a state class) that joins to other selectors for its parameters. Note: This property should not be explicitly set by anyone using versions of NGXS after v3; it only exists for migrating codebases from v3 to versions after v3. See the deprecation notice for further details.
* `compatibility` - A nested options object that allows for the following compatibility options:
  * `strictContentSecurityPolicy` - Set this to `true` in order to enable support for pages where a Strict Content Security Policy has been enabled. This setting circumvent some optimisations that violate a strict CSP through the use of `new Function(...)`. (Default value is `false`)

`ngxs.config.ts`:

> :warning: If your project lacks environment files, you can generate them using the `ng generate environments` command.

```ts
import { NgxsModuleOptions } from '@ngxs/store';

import { environment } from '../environments/environment';

export const ngxsConfig: NgxsModuleOptions = {
  developmentMode: !environment.production,
  selectorOptions: {
    suppressErrors: false
  },
  compatibility: {
    strictContentSecurityPolicy: true
  }
};
```

`app.config.ts`:

```ts
import { provideStore } from '@ngxs/store';

import { ngxsConfig } from './ngxs.config';

export const appConfig: ApplicationConfig = {
  providers: [provideStore(states, ngxsConfig)]
};
```


# Error Handling

## Deterministic vs Non-deterministic

Firstly, it is good to understand that your error handling approach should consider two different classes of error: Deterministic and Non-deterministic errors.

### Deterministic errors:

* These are repeatable errors that you would expect during the normal course of operation of your application.
* The condition for this error to happen is fully determined by the state of the application (hence the word "deterministic").
* `Determinism` is the property that you will always get the same output given the same input.
* If the application's data remains unchanged, then an erroring operation will always fail, no matter how many times it is retried.
* You should consider how your code should handle these errors as part of building a robust application.
* Some example approaches (from the 4xx HTTP status codes):
  * Bad request (400): The data that you are sending is in the incorrect format, something definitely needs to change with what you are sending.
  * Not Found (404): The requested item is not found, so you need to make a decision on how to respond to this scenario.

### Non-deterministic errors:

* These are errors generally occur as a result of the environment within which your application operates. For example, the network or a server failure could cause this type of error.
* Because this type of error lacks `Determinism` (see definition above), then it is possible that retrying the operation could lead to success. It is recommended to decide on a retry strategy that makes sense for the application experience that you wish to offer.
* Some example approaches (from the 5xx HTTP status codes - "server-side" errors ):
  * Internal Server Error (500): Something went wrong with the server. Things could succeed on retry, but it really depends on how resilient your server side is. Not recommended to retry for too long because this type of error could take more than a negligible time to resolve.
  * Gateway Timeout (504): There is a connection timeout, so it may be a good idea to check if there is network availability before retrying too many times.

## Recommended Approach in NGXS

It is recommended to handle errors within your `@Action` function in your state:

### Deterministic errors:

* `Update the state` to capture the error details
  * Ensure that the relevant selectors cater for these error states and provide information for your user to respond to the error accordingly
* OR `dispatch` an action that sends the error details to the necessary state or service
  * This action could be picked up by an application level error state or could be picked up by a service that is listening to the action stream (see [Actions Stream](/concepts/actions/actions-stream))

### Non-deterministic errors:

* Respond to the error accordingly(retry, abort, etc.)
* AND use one of the deterministic error handling mechanisms above to inform your user about the situation

## Fallback Error Handling

NGXS has a robost and predictable fallback mechanism for error handling. Although it is not recommended, some developers use these to tailor their application design to suit their team's preference.

Error handling firstly falls back to any error handler at the `dispatch` call and then to the `NgxsUnhandledErrorHandler`.

### Handling at the `dispatch` call

To manually catch an error thrown and not handled by an action, you can subscribe to the observable returned by the `dispatch` call and include an `error` callback. By subscribing and providing an `error` callback, NGXS won't pass the error to its final unhandled error handler.

You can include this error callback in three ways:

* by explicitly supplying the `error` callback in your `subscribe` function call
* by using one of the `rjxs` error handling operators
* by converting the observable into a promise and using any standard `async` or `promise` error handling mechanisms

Check this [special note](#ngxs-error-handling-detection-in-observables) if you have custom code that modifies rxjs's default error fallbacks.

#### Example

Given the following code:

```ts
class AppState {
  @Action(ActionThatCausesAnError)
  unhandledError(ctx: StateContext<StateModel>) {
    // error is thrown
  }
}
```

```ts
import { lastValueFrom } from 'rxjs';

class AppComponent {
  //...
  handleError() {
    this.store.dispatch(new ActionThatCausesAnError()).subscribe({
      error: error => {
        console.log('unhandled error on dispatch subscription: ', error);
      }
    });
  }

  async handleErrorAsync() {
    try {
      await latestValueFrom(this.store.dispatch(new ActionThatCausesAnError()));
    } catch (error) {
      console.log('unhandled error on dispatch caught: ', error);
    }
  }
}
```

You can play around with error handling in the following [stackblitz](https://stackblitz.com/edit/ngxs-error-handling)

### The `NgxsUnhandledErrorHandler`

The final level of fallback in NGXS will pass the error to the `NgxsUnhandledErrorHandler`. The default implementation of this service will pass the error on to the Angular `ErrorHandler` that is configured in the application.

The application developer can choose to provide a custom `NgxsUnhandledErrorHandler` to direct the error as they see fit.

#### Overriding the `NgxsUnhandledErrorHandler`

NGXS provides the `NgxsUnhandledErrorHandler` class, which you can override with your custom implementation to manage unhandled errors according to your requirements:

```ts
import { NgxsUnhandledErrorHandler, NgxsUnhandledErrorContext } from '@ngxs/store';

@Injectable()
export class MyCustomNgxsUnhandledErrorHandler {
  handleError(error: any, unhandledErrorContext: NgxsUnhandledErrorContext): void {
    // Do something with these parameters
  }
}

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: NgxsUnhandledErrorHandler,
      useClass: MyCustomNgxsUnhandledErrorHandler
    }
  ]
};
```

Note that the second parameter, `NgxsUnhandledErrorContext`, contains an object with an `action` property. This property holds the action that triggered the error while being processed.

## Special Notes

### NGXS Error Handling Detection in Observables

In order to acheive the detection of `dispatch` call error handling, NGXS configures the RxJS [`onUnhandledError`](https://rxjs.dev/api/index/interface/GlobalConfig#onUnhandledError) callback. This property is accessible in RxJS versions 7 and above, which is why NGXS mandates a minimum RxJS version of 7.

The RxJS `onUnhandledError` callback triggers whenever an unhandled error occurs within an observable and no `error` callback has been supplied.

:warning: If you configure `onUnhandledError` after NGXS has loaded, you will need to store the existing implementation in a local variable and invoke it when the error is not handled by your customized rxjs error strategy:

```ts
import { config } from 'rxjs';

const existingHandler = config.onUnhandledError;
config.onUnhandledError = function (error: any) {
  if (shouldWeHandleThis(error)) {
    // Do something with this error
  } else {
    existingHandler.call(this, error);
  }
};
```


# Meta Reducers

A meta reducer is a higher order reducer that allows you to take action on the global state rather than a state slice. In NGXS, we don't have this concept but you can accomplish this with [plugins](https://github.com/ngxs/store/blob/release/docs/concepts/store/broken-reference/README.md).

An example of a meta reducer might be to clear the entire state when a user logs out. An example implementation would be:

```ts
import { getActionTypeFromInstance } from '@ngxs/store';

export function logoutPlugin(state, action, next) {
  // Use the get action type helper to determine the type
  if (getActionTypeFromInstance(action) === Logout.type) {
    // if we are a logout type, lets erase all the state
    state = {};
  }

  // return the next function with the empty state
  return next(state, action);
}
```

Then add it to `provideStore` features:

```ts
import { provideStore, withNgxsPlugin } from '@ngxs/store';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], withNgxsPlugin(logoutPlugin))]
};
```

Now when we dispatch the logout action it will use our new plugin and erase the state.


# ACTIONS

Actions can either be thought of as a command which should trigger something to happen, or as the resulting event of something that has already happened.

Each action contains a `type` field which is its unique identifier.

## Internal Actions

There are two actions that get triggered in the internals of the library:

1. @@INIT - store being initialized, before all the [ngxsOnInit Life-cycle](/concepts/state/life-cycle) events.
2. @@UPDATE\_STATE - a new [lazy-loaded state](/concepts/state/lazy) being added to the store.

## Simple Action

Let's say we want to update the status of whether the animals have been fed in our Zoo. We would describe a class like:

```ts
export class FeedAnimals {
  static readonly type = '[Zoo] Feed Animals';
}
```

Later in our state class, we will listen to this action and mutate our state, in this case flipping a boolean flag.

## Actions with Metadata

Often you need an action to have some data associated with it. Here we have an action that should trigger feeding a zebra with hay.

```ts
export class FeedZebra {
  static readonly type = '[Zoo] Feed Zebra';

  constructor(
    public name: string,
    public hayAmount: number
  ) {}
}
```

The `name` field of the action class will represent the name of the zebra we should feed. The `hayAmount` tells us how many kilos of hay the zebra should get.

## Dispatching Actions

See [Store](/concepts/store) documentation for how to dispatch actions.

## How should you name your actions?

### Commands

Commands are actions that tell your app to do something. They are usually triggered by user events such as clicking on a button, or selecting something.

Names should contain three parts:

* A context as to where the command came from, `[User API]`, `[Product Page]`, `[Dashboard Page]`.
* A verb describing what we want to do with the entity.
* The entity we are acting upon, `User`, `Card`, `Project`.

Examples:

* `[User API] GetUser`
* `[Product Page] AddItemToCart`
* `[Dashboard Page] ArchiveProject`

### Event examples

Events are actions that have already happened and we now need to react to them.

The same naming conventions apply as commands, but they should always be in the past tense.

By using `API` in the context part of the action name we know that this event was fired because of an async action to an API.

Actions are normally dispatched from container components such as router pages. By having explicit actions for each page, it's also easier to track where an event came from.

Examples:

* \[User API] GetUserSuccess
* \[Project API] ProjectUpdateFailed
* \[User Details Page] PasswordChanged
* \[Project Stars Component] StarsUpdated

A great video on the topic is [Good Action Hygiene by Mike Ryan](https://www.youtube.com/watch?v=JmnsEvoy-gY) It's for NgRx, but the same naming conventions apply to NGXS.

## Group your actions

Don't suffix your actions:

```ts
export class AddTodo {
  static readonly type = '[Todo] Add';

  constructor(public payload: any) {}
}

export class EditTodo {
  static readonly type = '[Todo] Edit';

  constructor(public payload: any) {}
}

export class FetchAllTodos {
  static readonly type = '[Todo] Fetch All';
}

export class DeleteTodo {
  static readonly type = '[Todo] Delete';

  constructor(public id: number) {}
}
```

here we group similar actions into the `Todo` namespace. In this case just import namespace instead of multiple action classes in same file.

```ts
const ACTION_SCOPE = '[Todo]';

export namespace TodoActions {
  export class Add {
    static readonly type = `${ACTION_SCOPE} Add`;

    constructor(public payload: any) {}
  }

  export class Edit {
    static readonly type = `${ACTION_SCOPE} Edit`;

    constructor(public payload: any) {}
  }

  export class FetchAll {
    static readonly type = `${ACTION_SCOPE} Fetch All`;
  }

  export class Delete {
    static readonly type = `${ACTION_SCOPE} Delete`;

    constructor(public id: number) {}
  }
}
```


# Action Schematics

You can generate an `action` using the command as seen below:

```bash
ng generate @ngxs/store:actions
```

Running this command will prompt you to create an "Action" with the options as they are listed in the table below.

Alternatively, you can provide the options yourself.

```bash
ng generate @ngxs/store:actions --name NAME_OF_YOUR_ACTION
```

| Option | Description                                  | Required | Default Value        |
| ------ | -------------------------------------------- | :------: | -------------------- |
| --name | The name of the actions                      |    Yes   |                      |
| --path | The path to create the actions               |    No    | App's root directory |
| --flat | Boolean flag to indicate if a dir is created |    No    | `false`              |

🪄 **This command will**:

* Create an action with the given options

> Note: If the --flat option is false, the generated files will be organized into a directory named using the kebab case of the --name option. For instance, 'MyActions' will be transformed into 'my-actions'.


# Actions Life Cycle

This document describes the life cycle of actions, after reading it you should have a better understanding of how NGXS handles actions and what stages they may be at.

## Theory

Any action in NGXS can be in one of four states, these states are `DISPATCHED`, `SUCCESSFUL`, `ERRORED`, `CANCELED`, think of it as a finite state machine.

![Actions FSM](/files/-LkQ3Z6be3uvYnhKIEFJ)

NGXS has an internal stream of actions. When we dispatch any action using the following code:

```ts
store.dispatch(new GetNovels());
```

The internal actions stream emits an object called `ActionContext`, that has 2 properties:

```ts
{
  action: GetNovelsInstance,
  status: 'DISPATCHED'
}
```

There is an action stream listener that filters actions by `DISPATCHED` status and invokes the appropriate handlers for this action. After all processing for the action has completed it generates a new `ActionContext` with the following `status` value:

```ts
{
  action: GetNovelsInstance,
  status: 'SUCCESSFUL'
}
```

The observable returned by the `dispatch` method is then triggered after the action is handled "successfully" and, in response to this observable, you are able to do the actions you wanted to do on completion of the action.

If the `GetNovels` handler throws an error, for example:

```ts
@Action(GetNovels)
getNovels() {
  throw new Error('This is just a simple error!');
}
```

Then the following `ActionContext` will be created:

```ts
{
  action: GetNovelsInstance,
  status: 'ERRORED'
}
```

Actions can be both synchronous and asynchronous, for example if you send a request to your API and wait for the response. Asynchronous actions are handled in parallel, synchronous actions are handled one after another.

What about the `CANCELED` status? Only asynchronous actions can be canceled, this means that the new action was dispatched before the previous action handler finished doing some asynchronous job. Canceling actions can be achieved by providing options to the `@Action` decorator:

```ts
export class NovelsState {
  @Selector()
  static getNovels(state: Novel[]) {
    return state;
  }

  constructor(private novelsService: NovelsService) {}

  @Action(GetNovels, { cancelUncompleted: true })
  getNovels(ctx: StateContext<Novel[]>) {
    return this.novelsService.getNovels().pipe(
      tap(novels => {
        ctx.setState(novels);
      })
    );
  }
}
```

Imagine a component where you've got a button that dispatches the `GetNovels` action on click:

```ts
@Component({
  selector: 'app-novels',
  template: `
    @for (novel of novels(); track novel) {
      <app-novel [novel]="novel" />
    }

    <button (click)="getNovels()">Get novels</button>
  `,
  standalone: true,
  imports: [NovelComponent]
})
export class NovelsComponent {
  novels = this.store.selectSignal(NovelsState.getNovels);

  constructor(private store: Store) {}

  getNovels() {
    this.store.dispatch(new GetNovels());
  }
}
```

If you click the button twice - two actions will be dispatched and the previous action will be canceled because it's asynchronous. This works exactly the same as `switchMap`. If we didn't use NGXS - the code would look as follows:

```ts
@Component({
  selector: 'app-novels',
  template: `
    @for (novel of novels(); track novel) {
      <app-novel [novel]="novel" />
    }

    <button #button>Get novels</button>
  `
})
export class NovelsComponent implements OnInit {
  button = viewChild.required('button');

  novels = signal<Novel[]>([]);

  constructor(private novelsService: NovelsService) {}

  ngOnInit() {
    fromEvent(this.button().nativeElement, 'click')
      .pipe(switchMap(() => this.novelsService.getNovels()))
      .subscribe(novels => {
        this.novels.set(novels);
      });
  }
}
```

## Asynchronous actions

Let's talk more about asynchronous actions, imagine a simple state that stores different genres of books and has the following code:

```ts
export interface BooksStateModel {
  novels: Book[];
  detectives: Book[];
}

export class GetNovels {
  static type = '[Books] Get novels';
}

export class GetDetectives {
  static type = '[Books] Get detectives';
}

@State<BooksStateModel>({
  name: 'books',
  defaults: {
    novels: [],
    detectives: []
  }
})
@Injectable()
export class BooksState {
  constructor(private booksService: BooksService) {}

  @Action(GetNovels)
  getNovels(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getNovels().pipe(
      tap(novels => {
        ctx.patchState({ novels });
      })
    );
  }

  @Action(GetDetectives)
  getDetectives(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getDetectives().pipe(
      tap(detectives => {
        ctx.patchState({ detectives });
      })
    );
  }
}
```

Let's say that you dispatch `GetNovels` and `GetDetectives` actions separately like this:

```ts
store
  .dispatch(new GetNovels())
  .subscribe(() => {
    ...
  });

store
  .dispatch(new GetDetectives())
  .subscribe(() => {
    ...
  });
```

You could correctly assume that the request for `GetNovels` would be dispatched before `GetDetectives`. This is true due to the synchronous nature of the dispatch, but their action handlers are asynchronous so you can't be sure which HTTP response would return first. In this example we dispatch the `GetNovels` action before `GetDetectives`, but if the call to fetch novels takes longer then the `novels` property will be set after `detectives`. The `store.dispatch` function returns an observable that can be used to respond to the completion of each of these actions.

Alternatively you could dispatch an array of actions:

```ts
store
  .dispatch([
    new GetNovels(),
    new GetDetectives()
  ])
  .subscribe(() => {
    ...
  });
```

The order of dispatch would be the same as the previous example, but in this code we are able to subscribe to an observable from the `store.dispatch` function that will fire only when both actions have completed. The below diagram demonstrates how asynchronous actions are handled under the hood:

![Life cycle](/files/-LkQ3Z7UqKjOCF6LbKlt)

## Error life cycle

So, how are errors handled in this regard? Let's say that you dispatch multiple actions at the same time like this:

```ts
store
  .dispatch([
    new GetNovelById(id), // action handler throws `new Error(...)`
    new GetDetectiveById(id)
  ])
  .subscribe({
    next: () => {
      // they will never see me
    },
    error: error => {
      console.log(error); // `Error` that was thrown by the `getNovelById` handler
    }
  });
```

Because at least one action throws an error NGXS returns an error to the `onError` observable callback and neither the `onNext` or `onComplete` callbacks would be called.

## Asynchronous Actions continued - "Fire and forget" vs "Fire and wait"

In NGXS, when you do asynchronous work you should return an `Observable` or `Promise` from your `@Action` method that represents that asynchronous work (and completion). The completion of the action will then be bound to the completion of the asynchronous work. If you use the `async/await` javascript syntax then NGXS will know about the completion because an `async` method returns the `Promise` for you. If you return an `Observable` NGXS will subscribe to the observable for you and bind the action's completion lifecycle event to the completion of the `Observable`.

The "fire-and-forget" approach refers to performing asynchronous work inside an action handler without returning anything from the method. This approach is not recommended because state writes are no longer allowed once the action handler "completes". When you don't return anything (effectively using a `void` return type), state writes are disabled immediately after the synchronous part of the handler finishes executing:

```ts
@Action(GetNovels)
getNovels(ctx: StateContext<BooksStateModel>) {
  this.booksService.getNovels().subscribe(novels => {
    // This code will not patch the state because `patchState` is disabled
    // after the `GetNovels` handler has finished executing.
    ctx.patchState({ novels });
  });
}
```

Another more common use case of using the "fire and forget" approach would be when you dispatch a new action inside a handler and you don't want to wait for the "child" action to complete. For example, if we want to load detectives right after novels but we don't want the completion of our `GetNovels` action to wait for the detectives to load then we would have the following code:

```ts
export class BooksState {
  constructor(private booksService: BooksService) {}

  @Action(GetNovels)
  getNovels(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getNovels().pipe(
      tap(novels => {
        ctx.patchState({ novels });
        ctx.dispatch(new GetDetectives());
      })
    );
  }

  @Action(GetDetectives)
  getDetectives(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getDetectives().pipe(
      tap(detectives => {
        ctx.patchState({ detectives });
      })
    );
  }
}
```

Here the `GetDetectives` action would be dispatched just before the `GetNovels` action completes. The `GetDetectives` action is just a "fire and forget" as far as the `GetNovels` action is concerned. To be clear, NGXS will wait for a response from the `getNovels` service call, then it will populate a new state with the returned novels, then it will dispatch the new `GetDetectives` action (which kicks off another asynchronous request), and then `GetNovels` would move into its' success state (without waiting for the completion of the `GetDetectives` action):

```ts
store.dispatch(new GetNovels()).subscribe(() => {
  // they will see me, but detectives will be still loading in the background
});
```

If you want the `GetNovels` action to wait for the `GetDetectives` action to complete, you will have to use `mergeMap` operator (or any operator that maps to the inner `Observable`, like `concatMap`, `switchMap`, `exhaustMap`) so that the `Observable` returned by the `@Action` method has bound its completion to the inner action's completion:

```ts
@Action(GetNovels)
getNovels(ctx: StateContext<BooksStateModel>) {
  return this.booksService.getNovels().pipe(
    tap(novels => {
      ctx.patchState({ novels });
    }),
    mergeMap(() => ctx.dispatch(new GetDetectives()))
  );
}
```

Often this type of code can be made simpler by converting to Promises and using the `async/await` syntax. The same method would be as follows:

```ts
@Action(GetNovels)
async getNovels(ctx: StateContext<BooksStateModel>) {
  const novels = await firstValueFrom(this.booksService.getNovels());
  ctx.patchState({ novels });
  await firstValueFrom(ctx.dispatch(new GetDetectives()));
}
```

Note: leaving out the final `await` keyword here would cause this to be "fire and forget" again.

## Handling Cancellation with AbortSignal

When using `cancelUncompleted`, NGXS provides an `abortSignal` property on the `StateContext` (available in v21+) that allows you to detect and respond to action cancellation. This is especially useful when working with async/await:

```ts
@Action(GetNovels, { cancelUncompleted: true })
async getNovels(ctx: StateContext<Novel[]>) {
  // Perform async work
  const novels = await firstValueFrom(this.booksService.getNovels());

  // Check if action was canceled before updating state
  if (ctx.abortSignal.aborted) {
    return; // Exit gracefully without updating state
  }

  ctx.setState(novels);
}
```

The `abortSignal` can also be passed directly to the Fetch API:

```ts
@Action(SearchBooks, { cancelUncompleted: true })
async searchBooks(ctx: StateContext<BooksStateModel>, action: SearchBooks) {
  try {
    const response = await fetch(`/api/books?q=${action.query}`, {
      signal: ctx.abortSignal // Automatically cancels the request
    });

    const books = await response.json();
    ctx.patchState({ books });
  } catch (error) {
    if (error.name === 'AbortError') {
      return; // Gracefully handle cancellation
    }
    throw error;
  }
}
```

When you return an Observable from an action handler, NGXS automatically unsubscribes when the action is canceled, so you don't need to manually check the `abortSignal`.

For more details on action cancellation, see the [Cancellation guide](/concepts/actions/cancellation).

## Summary

In summary - any dispatched action starts with the status `DISPATCHED`. Next, NGXS looks for handlers that listen to this action, if there are any — NGXS invokes them and processes the return value and errors. If the handler has done some work and has not thrown an error, the status of the action changes to `SUCCESSFUL`. If something went wrong while processing the action (for example, if the server returned an error) then the status of the action changes to `ERRORED`. And if an action handler is marked as `cancelUncompleted` and a new action has arrived before the old one was processed then NGXS interrupts the processing of the first action and sets the action status to `CANCELED`.


# Actions Stream

Before reading this article, we advise you to become acquainted with the [actions life cycle](/concepts/actions/actions-life-cycle).

Event sourcing involves modeling the state changes made by applications as an immutable sequence or “log” of events.\
Instead of focusing on current state, you focus on the changes that have occurred over time. It is the practice of\
modeling your system as a sequence of events. In NGXS, we called this the Actions Stream.

Typically actions directly correspond to state changes but it can be difficult to always make your component react\
based on state. As a side effect of this paradigm, we end up creating lots of intermediate state properties\
to do things like reset a form/etc. The Actions Stream lets us drive our components based on state along with events\
that are emitted.

For example, if we were to have a shopping cart and we were to delete an item out of it you might want to show\
a notification that it was successfully removed. In a pure state driven application, you might create some kind\
of message array to make the dialog show up. With the Actions Stream, we can respond to the action directly.

The Actions Stream is an Observable that receives all the actions dispatched before the state takes any action on it.

Actions in NGXS also have a lifecycle. Since any potential action can be async we tag actions showing when they are "DISPATCHED", "SUCCESSFUL", "CANCELED" or "ERRORED". This gives you the ability to react to actions at different points in their existence.

Since the actions stream is an Observable, we can use the following operators inside a `pipe(..)`:

* `ofAction`: triggers when any of the below lifecycle events happen
* `ofActionDispatched`: triggers when an action has been dispatched
* `ofActionSuccessful`: triggers when an action has been completed successfully
* `ofActionCanceled`: triggers when an action has been canceled
* `ofActionErrored`: triggers when an action has caused an error to be thrown
* `ofActionCompleted`: triggers when an action has been completed whether it was successful or not (returns completion summary)

All of the above pipes return the original `action` in the observable except for the `ofActionCompleted` pipe which returns some summary information for the completed action. This summary is an object with the following interface:

```ts
interface ActionCompletion<T = any> {
  action: T;
  result: {
    successful: boolean;
    canceled: boolean;
    error?: Error;
  };
}
```

Below is a action handler that filters for `RouteNavigate` actions and then tells the router to navigate to that\
route.

```ts
import { Injectable, inject } from '@angular/core';
import { Actions, ofActionDispatched } from '@ngxs/store';

@Injectable({ providedIn: 'root' })
export class RouteHandler implements OnDestroy {
  private destroy$ = new Subject<void>();

  constructor() {
    const actions$ = inject(Actions);
    const router = inject(Router);

    actions$
      .pipe(ofActionDispatched(RouteNavigate), takeUntil(this.destroy$))
      .subscribe(({ payload }) => router.navigate([payload]));
  }

  ngOnDestroy(): void {
    this.destroy$.next();
  }
}
```

Remember to ensure that you inject the `RouteHandler` somewhere in your application for DI to set things up. If you want this to occur during application startup, this can also be accomplished using the new `ENVIRONMENT_INITIALIZER` token:

```ts
import { ApplicationConfig, ENVIRONMENT_INITIALIZER, inject } from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: ENVIRONMENT_INITIALIZER,
      multi: true,
      useValue: () => inject(RouteHandler)
    }
  ]
};
```

The Actions Stream can also be utilized in components. For example, considering the cart deletion scenario, we could use the following code:

```ts
@Component({ ... })
export class CartComponent {
  constructor() {
    const actions$ = inject(Actions);

    actions$.pipe(ofActionSuccessful(CartDelete)).subscribe(() => alert('Item deleted'));
  }
}
```

Also, remember to unsubscribe from the Actions Stream at the end:

```ts
@Component({ ... })
export class CartComponent {
  constructor() {
    const actions$ = inject(Actions);

    actions$
      .pipe(ofActionSuccessful(CartDelete), takeUntilDestroyed())
      .subscribe(() => alert('Item deleted'));
  }
}
```


# Cancellation

If you have an async action, you may want to cancel a previous Observable if the action has been dispatched again. This is useful for canceling previous requests like in a typeahead.

## Basic

For basic scenarios, we can use the `cancelUncompleted` action decorator option.

```ts
import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService, private actions$: Actions) {}

  @Action(FeedAnimals, { cancelUncompleted: true })
  get(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.get(action.payload).pipe(
      tap((res) => ctx.setState(res))
    ));
  }
}
```

## Using AbortSignal

Starting from NGXS v21, the `StateContext` includes an `abortSignal` property that provides a standardized way to handle cancellation of asynchronous operations. This is particularly useful when working with `cancelUncompleted` actions.

### Why AbortSignal?

The `AbortSignal` provides a standard browser API to detect and respond to cancellations. When an action marked with `cancelUncompleted: true` is canceled (because a new instance was dispatched), the `abortSignal` will be aborted, allowing you to:

* Check cancellation status in async/await code
* Pass the signal to fetch requests for automatic cancellation
* Clean up resources gracefully
* Avoid unnecessary state updates

### With Async/Await

When using async/await, check `ctx.abortSignal.aborted` after await points to handle cancellation:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

export class FetchAnimals {
  static readonly type = '[Zoo] Fetch Animals';
}

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FetchAnimals, { cancelUncompleted: true })
  async fetchAnimals(ctx: StateContext<ZooStateModel>) {
    // Perform async work
    const animals = await this.animalService.getAnimals();

    // Check if canceled before updating state
    if (ctx.abortSignal.aborted) {
      console.log('Action was canceled, skipping state update');
      return;
    }

    ctx.setState({ animals });
  }
}
```

### With Fetch API

The `AbortSignal` works seamlessly with the Fetch API:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

export class SearchAnimals {
  static readonly type = '[Zoo] Search Animals';
  constructor(public query: string) {}
}

@State<ZooStateModel>({
  defaults: {
    animals: [],
    loading: false
  }
})
@Injectable()
export class ZooState {
  @Action(SearchAnimals, { cancelUncompleted: true })
  async searchAnimals(ctx: StateContext<ZooStateModel>, action: SearchAnimals) {
    ctx.patchState({ loading: true });

    try {
      // Pass the abort signal directly to fetch
      const response = await fetch(`/api/animals?q=${action.query}`, {
        signal: ctx.abortSignal
      });

      const animals = await response.json();
      ctx.patchState({ animals, loading: false });
    } catch (error) {
      // Handle abort gracefully
      if (error.name === 'AbortError') {
        console.log('Search was canceled');
        return; // Don't update state or rethrow
      }

      // Handle other errors
      ctx.patchState({ loading: false });
      throw error;
    }
  }
}
```

### With Observables

When you return an Observable from an action handler, NGXS automatically unsubscribes when the `abortSignal` is aborted. You don't need to manually check the signal:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { tap } from 'rxjs';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals, { cancelUncompleted: true })
  feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    // Observable will be automatically unsubscribed if action is canceled
    return this.animalService
      .get(action.payload)
      .pipe(tap(animals => ctx.setState({ animals })));
  }
}
```

## Advanced

For more advanced cases, we can use normal Rx operators.

```ts
import { Injectable } from '@angular/core';
import { State, Action, Actions, ofAction } from '@ngxs/store';
import { tap } from 'rxjs';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService, private actions$: Actions) {}

  @Action(FeedAnimals)
  get(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.get(action.payload).pipe(
      tap((res) => ctx.setState(res)),
      takeUntil(this.actions$.pipe(ofAction(RemoveTodo)))
    ));
  }
}
```


# Dynamic Action Handlers

Sometimes you need to attach action handlers dynamically after state initialization. For example, you might want to:

* Add action handlers conditionally based on runtime conditions
* Add action handlers for lazy-loaded modules
* Add temporary action handlers that can be removed later

How is a Dynamic Action Handler different to what the [Actions Stream](/concepts/actions/actions-stream) gives you?

* It gives you the ability to make changes to state from your handler
* It participates in the standard [actions life cycle](/concepts/actions/actions-life-cycle)
  * The result of the handler will affect the completion result of the action
  * The life cycle for the action will only complete once all dynamic handlers have completed too

NGXS provides the `ActionDirector` service for registering Dynamic Action Handlers.

## DISCLAIMER: Before you use it...

Please bear in mind that this is a power user feature, and should not be used as a replacement for the typical action declarations within a state.

* Overuse of Dynamic Action Handlers can lead to an application that is hard to understand and hard to determine the exact behavior of a state at a specific point in time
* Co-location of the handlers with a state class is a massive benefit for a clean and predictable codebase. When using Dynamic Action Handlers, please consider this fact and try to honour this principle
* The main intended use of this feature is for plugins and utilities that enhance state, so if you are doing something else, please check that you can't solve your problem with the simpler state constructs
* Another potential use is for the lazy loading of action handler logic. This is a very specialised optimisation and should only be used if lazy loading the entire state with a route is not sufficient

## The ActionDirector Service

The `ActionDirector` allows you to attach action handlers to a state at any point after initialization and gives you the ability to detach them when no longer needed.

### Attaching an Action Handler

```ts
import { ActionDirector, createSelector } from '@ngxs/store';
import { inject, Injectable } from '@angular/core';

// State token
const COUNTRIES_STATE_TOKEN = new StateToken<string[]>('countries');

// Action
export class AddCountry {
  static readonly type = '[Countries] Add Country';

  constructor(readonly country: string) {}
}

@Injectable({ providedIn: 'root' })
export class CountryService {
  private actionDirector = inject(ActionDirector);
  private handle: { detach: () => void } | null = null;

  // Attach the action handler
  attachCountryHandler() {
    if (this.handle) return; // Already attached

    this.handle = this.actionDirector.attachAction(
      COUNTRIES_STATE_TOKEN,
      AddCountry,
      (ctx, action) => {
        // Update state
        ctx.setState(countries => [...countries, action.country]);
      }
    );
  }

  // Detach the action handler when no longer needed
  detachCountryHandler() {
    this.handle?.detach();
    this.handle = null;
  }
}
```

### When to Use Dynamic Action Handlers

Dynamic action handlers are useful in several scenarios:

1. **Plugin systems**: Allow plugins to register their own action handlers
2. **Lazy-loaded features**: Attach action handlers when a feature module is loaded
3. **Temporary behaviors**: Create handlers that only exist for a specific duration
4. **Conditional action handling**: Enable action handlers based on runtime conditions

### The detach Function

The `attachAction` method returns an object with a `detach` function that can be called to remove the action handler. This enables proper cleanup and prevents memory leaks.

```ts
// Example of attaching and later detaching a handler
const handle = actionDirector.attachAction(STATE_TOKEN, SomeAction, (ctx, action) => {
  // Handler logic
});

// Later, when the handler is no longer needed:
handle.detach();
```


# Monitoring Unhandled Actions

We can know if we have dispatched some actions which haven't been handled by any of the NGXS states. This is useful to monitor if we dispatch actions at the right time. For instance, dispatched actions might be coming from the WebSocket, but the action handler is located within the feature state that has not been registered yet. This will let us know that we should either register the state earlier or do anything else from the code perspective because actions are not being handled.

This may be enabled by adding the `withNgxsDevelopmentOptions` to `provideStore`:

```ts
import { provideStore, withNgxsDevelopmentOptions } from '@ngxs/store';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsDevelopmentOptions({
        warnOnUnhandledActions: true
      })
    )
  ]
};
```

If you are still using modules, include the `NgxsDevelopmentModule` plugin in your root app module:

```ts
import { NgxsModule, NgxsDevelopmentModule } from '@ngxs/store';

@NgModule({
  imports: [
    NgxsModule.forRoot([]),
    NgxsDevelopmentModule.forRoot({
      warnOnUnhandledActions: true
    })
  ]
})
export class AppModule {}
```

Setting `warnOnUnhandledActions` to a truthy value will tell the logger to warn on any unhandled action.

## Ignoring Certain Actions

We can ignore specific actions that should not be logged if they have never been handled. For instance, if we're using the `@ngxs/router-plugin` and don't care about router actions like `RouterNavigation`, then we may add it to the `ignore` array:

```ts
import { provideStore, withNgxsDevelopmentOptions } from '@ngxs/store';
import { RouterNavigation, RouterCancel } from '@ngxs/router-plugin';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsDevelopmentOptions({
        warnOnUnhandledActions: true
      })
    )
  ]
};
```

> 💡 It's best to import this module only in development mode. This may be achieved using environment imports. See [dynamic plugins](/recipes/dynamic-plugins).

Ignored actions can be also expanded in lazy modules. The `@ngxs/store` exposes the `NgxsUnhandledActionsLogger` for these purposes:

```ts
import { inject, ENVIRONMENT_INITIALIZER } from '@angular/core';
import { NgxsUnhandledActionsLogger } from '@ngxs/store';

declare const ngDevMode: boolean;

const providers = [provideStates([LazyState])];

if (ngDevMode) {
  providers.push({
    provide: ENVIRONMENT_INITIALIZER,
    multi: true,
    useValue: () => {
      const unhandledActionsLogger = inject(NgxsUnhandledActionsLogger);
      unhandledActionsLogger.ignoreActions(LazyAction);
    }
  });
}

export const routes: Routes = [
  {
    path: '',
    component: LazyComponent,
    providers
  }
];
```

The `ngDevMode` is a specific variable provided by Angular in development mode and by Angular CLI (to Terser) in production mode. This allows tree-shaking `NgxsUnhandledActionsLogger` stuff since the `NgxsDevelopmentModule` is imported only in development mode. It's never functional in production mode.


# STATE

States are classes that define a state container.

## Defining a State

States are classes along with decorators to describe metadata and action mappings. To define a state container, let's create an ES2015 class and decorate it with the `State` decorator.

```ts
import { Injectable } from '@angular/core';
import { State } from '@ngxs/store';

@State<string[]>({
  name: 'animals',
  defaults: []
})
@Injectable()
export class AnimalsState {}
```

In the state decorator, we define some metadata about the state. These options include:

* `name`: The name of the state slice. Note: The name is a required parameter and must be unique for the entire application. Names must be object property safe, (e.g. no dashes, dots, etc).
* `defaults`: Default set of object/array for this state slice.
* `children`: Child sub state associations (it's **deprecated** and slated for removal in the future, so it's advisable not to use it in newer applications).

Our states can also participate in dependency injection. This is hooked up automatically so all you need to do is inject your dependencies in the constructor.

```ts
@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feed: false
  }
})
@Injectable()
export class ZooState {
  constructor(private zooService: ZooService) {}
}
```

## (Optional) Defining State Token

Optionally, you can choose to replace the `name` of your state with a state token:

```ts
const ZOO_STATE_TOKEN = new StateToken<ZooStateModel>('zoo');

@State({
  name: ZOO_STATE_TOKEN,
  defaults: {
    feed: false
  }
})
@Injectable()
export class ZooState {
  constructor(private zooService: ZooService) {}
}
```

This slightly more advanced approach has some benefits which you can read more about in the [State Token](/concepts/state/token) section.

## Defining Actions

Our states listen to actions via an `@Action` decorator. The action decorator accepts an action class or an array of action classes.

### Simple Actions

Let's define a state that will listen to a `FeedAnimals` action to toggle whether the animals have been fed:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';
}

export interface ZooStateModel {
  feed: boolean;
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feed: false
  }
})
@Injectable()
export class ZooState {
  @Action(FeedAnimals)
  feedAnimals(ctx: StateContext<ZooStateModel>) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      feed: !state.feed
    });
  }
}
```

The `feedAnimals` function has one argument called `ctx` with a type of `StateContext<ZooStateModel>`. This context state has a slice pointer and several functions and properties for managing state:

* `getState()`: Returns the freshest state slice from the global store. When performing async operations the state is always fresh when you call this method.
* `setState()`: Sets the entire state to a new value
* `patchState()`: Patches only the specified properties
* `dispatch()`: Dispatches one or more actions
* `abortSignal`: An `AbortSignal` tied to the action's lifecycle (available in NGXS v21+). This allows you to handle cancellation of async operations, especially useful with `cancelUncompleted` actions.

It's important to note that the `getState()` method will always return the freshest state slice from the global store each time it is accessed. This ensures that when we're performing async operations the state is always fresh. If you want a snapshot, you can always clone the state in the method.

### Actions with a payload

Actions can also pass along metadata that has to do with the action. Say we want to pass along how much hay and carrots each zebra needs.

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

// This is an interface that is part of your domain model
export interface ZebraFood {
  name: string;
  hay: number;
  carrots: number;
}

// naming your action metadata explicitly makes it easier to understand what the action
// is for and makes debugging easier.
export class FeedZebra {
  static readonly type = '[Zoo] FeedZebra';

  constructor(public zebraToFeed: ZebraFood) {}
}

export interface ZooStateModel {
  zebraFood: ZebraFood[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    zebraFood: []
  }
})
@Injectable()
export class ZooState {
  @Action(FeedZebra)
  feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      zebraFood: [
        ...state.zebraFood,
        // this is the new ZebraFood instance that we add to the state
        action.zebraToFeed
      ]
    });
  }
}
```

In this example, we have a second argument that represents the action and we destructure it to pull out the name, hay, and carrots which we then update the state with.

There is also a shortcut `patchState` function to make updating the state easier. In this case, you only pass it the properties you want to update on the state and it handles the rest. The above function could be reduced to this:

```ts
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
  const state = ctx.getState();
  ctx.patchState({
    zebraFood: [
      ...state.zebraFood,
      action.zebraToFeed,
    ]
  });
}
```

The `setState` function can also be called with a function which will be given the existing state and should return the new state. All immutability concerns need to be honoured by this function.

For comparison, here are the two ways that you can invoke the `setState` function...\
With a new constructed state value:

```ts
@Action(MyAction)
addValue(ctx: StateContext, { payload }: MyAction) {
  ctx.setState({ ...ctx.getState(), value: payload  });
}
```

With a function that returns the new state value:

```ts
@Action(MyAction)
addValue(ctx: StateContext, { payload }: MyAction) {
  ctx.setState((state) => ({ ...state, value: payload }));
}
```

You may ask *"How is this valuable?"*. Well, it opens the door for refactoring of your immutable updates into `state operators` so that your code can become more declarative as opposed to imperative. You can find more details in our [state operators](https://www.ngxs.io/advanced/operators) documentation.

As another example you could use a library like [immer](https://github.com/mweststrate/immer) that can handle the immutability updates for you and provide a different way of expressing your immutable update through direct mutation of a draft object. We can use this external library because it supports the same signature as our `state operators` through their curried `produce` function. Here is the example from above expressed in this way:

```ts
import produce from 'immer';

// in class ZooState ...
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
  ctx.setState(produce((draft) => {
    draft.zebraFood.push(action.zebraToFeed);
  }));
}
```

Here the `produce` function from the `immer` library is called with just a single parameter so that it returns its [curried form](https://immerjs.github.io/immer/curried-produce) that will take a value and return a new value with all the expressed changes applied.

This approach can also allow for the creation of well named helper functions that can be shared between handlers that require the same type of update. The above example could be refactored to this:

```ts
// in class ZooState ...
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
  ctx.setState(addToZebraFood(action.zebraToFeed));
}

// defined elsewhere
import produce from 'immer';

function addToZebraFood(itemToAdd) {
  return produce((draft) => {
    draft.zebraFood.push(itemToAdd);
  });
}
```

### Async Actions

Actions can perform async operations and update the state after an operation.

Typically in Redux your actions are pure functions and you have some other system like a saga or an effect to perform these operations and dispatch another action back to your state to mutate it. There are some reasons for this, but for the most part it can be redundant and just add boilerplate. The great thing here is we give you the flexibility to make that decision yourself based on your requirements.

Let's take a look at a simple async action:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { tap } from 'rxjs';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';

  constructor(public animalsToFeed: string) {}
}

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals)
  feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.feed(action.animalsToFeed).pipe(
      tap(animalsToFeedResult => {
        const state = ctx.getState();
        ctx.setState({
          ...state,
          feedAnimals: [...state.feedAnimals, animalsToFeedResult]
        });
      })
    );
  }
}
```

In this example, we reach out to the animal service and call `feed` and then call `setState` with the result. Remember that we can guarantee that the state is fresh since the state property is a getter back to the current state slice.

You might notice we returned the Observable and just did a `tap`. If we return the Observable, the framework will automatically subscribe to it for us, so we don't have to deal with that ourselves. Additionally, if we want the stores `dispatch` function to be able to complete only once the operation is completed, we need to return that so it knows that.

Observables are not a requirement, you can use promises too. We could swap that observable chain to look like this:

```ts
import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';

  constructor(public animalsToFeed: string) {}
}

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals)
  async feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    const result = await this.animalService.feed(action.animalsToFeed);
    const state = ctx.getState();
    ctx.setState({
      ...state,
      feedAnimals: [...state.feedAnimals, result]
    });
  }
}
```

### Handling Cancellation in Async Actions

When using `cancelUncompleted` with async/await, you can use the `abortSignal` property to gracefully handle cancellation:

```ts
import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';

  constructor(public animalsToFeed: string) {}
}

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals, { cancelUncompleted: true })
  async feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    const result = await this.animalService.feed(action.animalsToFeed);

    // Check if action was canceled before updating state
    if (ctx.abortSignal.aborted) {
      return; // Exit gracefully without updating state
    }

    const state = ctx.getState();
    ctx.setState({
      ...state,
      feedAnimals: [...state.feedAnimals, result]
    });
  }
}
```

### Dispatching Actions From Actions

If you want your action to dispatch another action, you can use the `dispatch` function that is contained in the state context object.

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { map } from 'rxjs';

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  /**
   * Simple Example
   */
  @Action(FeedAnimals)
  feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      feedAnimals: [...state.feedAnimals, action.animalsToFeed]
    });

    return ctx.dispatch(new TakeAnimalsOutside());
  }

  /**
   * Async Example
   */
  @Action(FeedAnimals)
  feedAnimals2(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.feed(action.animalsToFeed).pipe(
      tap(animalsToFeedResult => {
        const state = ctx.getState();
        ctx.patchState({
          feedAnimals: [...state.feedAnimals, animalsToFeedResult]
        });
      }),
      mergeMap(() => ctx.dispatch(new TakeAnimalsOutside()))
    );
  }
}
```

Notice we returned the dispatch function, this goes back to our example above with async operations and the dispatcher subscribing to the result. It is not required though.


# State Schematics

You can generate a `state` using the command as seen below:

```bash
ng generate @ngxs/store:state
```

Running this command will prompt you to create a "State" with the options as they are listed in the table below.

Alternatively, you can provide the options yourself.

```bash
ng generate @ngxs/store:state --name NAME_OF_YOUR_STATE
```

| Option    | Description                                                    | Required | Default Value               |
| --------- | -------------------------------------------------------------- | :------: | --------------------------- |
| --name    | The name of the state                                          |    Yes   |                             |
| --path    | The path to create the state                                   |    No    | App's root directory        |
| --spec    | Boolean flag to indicate if a unit test file should be created |    No    | `true`                      |
| --flat    | Boolean flag to indicate if a dir is created                   |    No    | `false`                     |
| --project | Name of the project as it is defined in your angular.json      |    No    | Workspace's default project |

> When working with multiple projects within a workspace, you can explicitly specify the `project` where you want to install the **state**. The schematic will automatically detect whether the provided project is a standalone or not, and it will generate the necessary files accordingly.

🪄 **This command will**:

* Create a state with the given options

> Note: If the --flat option is false, the generated files will be organized into a directory named using the kebab case of the --name option. For instance, 'MyState' will be transformed into 'my-state'.


# Life-cycle

States can implement life-cycle events.

## `ngxsOnChanges`

If a state implements the `NgxsOnChanges` interface, its `ngxsOnChanges` method responds when the state is (re)set.

The `ngxsOnChanges` methods of states are invoked in a topologically sorted order, going from parent to child states. Within these methods, the first parameter is the `NgxsSimpleChange` object containing the current and previous states.

```ts
export interface ZooStateModel {
  animals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState implements NgxsOnChanges {
  ngxsOnChanges(change: NgxsSimpleChange) {
    console.log('prev state', change.previousValue);
    console.log('next state', change.currentValue);
  }
}
```

## `ngxsOnInit`

If a state implements the `NgxsOnInit` interface, its `ngxsOnInit` method is invoked after the `InitState` or `UpdateState` action has been handled, depending on where the state is registered (root or feature). If your state is provided at the root level, its `ngxsOnInit` may be called immediately once the `ENVIRONMENT_INITIALIZER` token is resolved. However, it may also be called asynchronously if you handle the `InitState` action and have some asynchronous logic.

The `ngxsOnInit` methods of states are invoked in a topologically sorted order, going from parent to child states. Within these methods, the first parameter is the `StateContext`, which allows you to access the current state and dispatch actions as usual.

```ts
export interface ZooStateModel {
  animals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState implements NgxsOnInit {
  ngxsOnInit(ctx: StateContext<ZooStateModel>) {
    console.log('State initialized, now getting animals');
    ctx.dispatch(new GetAnimals());
  }
}
```

## `ngxsAfterBootstrap`

If a state implements the `NgxsAfterBootstrap` interface, its `ngxsAfterBootstrap` method will be bound to the `APP_BOOTSTRAP_LISTENER`, which is resolved after the app has been bootstrapped.

```ts
export interface ZooStateModel {
  animals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState implements NgxsAfterBootstrap {
  ngxsAfterBootstrap(ctx: StateContext<ZooStateModel>) {
    console.log('The application has been fully rendered');
    ctx.dispatch(new GetAnimals());
  }
}
```

## Lifecycle sequence

After creating the state by calling its constructor, NGXS calls the lifecycle hook methods in the following sequence at specific moments:

| Hook                 | Purpose and Timing                                                                                       |
| -------------------- | -------------------------------------------------------------------------------------------------------- |
| ngxsOnChanges()      | Called *before* `ngxsOnInit()` and whenever state changes.                                               |
| ngxsOnInit()         | Called *once*, after the *first* `ngxsOnChanges()` and *before* the `APP_INITIALIZER` token is resolved. |
| ngxsAfterBootstrap() | Called *once*, after the root view and all its children have been rendered.                              |

## Feature States Order of Providers

If you have feature states they need to be registered after the root `provideStore` has been called:

```ts
// some-data-access-library/index.ts
export function provideDataAccessInvoiceLines() {
  return provideStates([InvoiceLinesState]);
}

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [provideStore(), provideDataAccessInvoiceLines()]
};
```

<details>

<summary>If you are still using modules</summary>

If you have feature modules they need to be imported after the root module:

```ts
// feature.module.ts
@NgModule({
  imports: [NgxsModule.forFeature([FeatureState])]
})
export class FeatureModule {}

// app.module.ts
@NgModule({
  imports: [NgxsModule.forRoot([]), FeatureModule]
})
export class AppModule {}
```

</details>

## APP\_INITIALIZER Stage

### Theoretical Introduction

The `APP_INITIALIZER` is just a token that references Promise factories. If you've ever used the `APP_INITIALIZER` token, then you are already familiar with its syntax:

```ts
export function appInitializerFactory() {
  return () => Promise.resolve();
}

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: appInitializerFactory,
      multi: true
    }
  ]
};
```

Please refer to [this guide](https://angular.io/api/core/APP_INITIALIZER) to familiarize yourself with its functionality.

### APP\_INITIALIZER and NGXS

The `APP_INITIALIZER` token is resolved after NGXS states are registered. This is because they are registered during the resolution of the `ENVIRONMENT_INITIALIZER` token. Additionally, the `ngxsOnInit` method on states is invoked before the `APP_INITIALIZER` token is resolved. Given the following code:

```ts
@Injectable({ providedIn: 'root' })
export class ConfigService {
  private version: string | null = null;

  private http = inject(HttpClient);

  loadVersion(): Observable<string> {
    return this.http.get<string>('/api/version').pipe(
      tap(version => {
        this.version = version;
      })
    );
  }

  getVersion(): never | string {
    if (this.version === null) {
      throw new Error('"version" is not available yet!');
    }

    return this.version;
  }
}

@State<string | null>({
  name: 'version',
  defaults: null
})
@Injectable()
export class VersionState implements NgxsOnInit {
  private configService = inject(ConfigService);

  ngxsOnInit(ctx: StateContext<string | null>) {
    ctx.setState(this.configService.getVersion());
  }
}

export function appInitializerFactory() {
  const configService = inject(ConfigService);
  return () => configService.loadVersion();
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore([VersionState]),

    {
      provide: APP_INITIALIZER,
      useFactory: appInitializerFactory,
      multi: true
    }
  ]
};
```

The example provided is for demonstration purposes and will throw an error because the `version` is not set yet. This occurs because `getVersion` is called before the version is loaded.

### Solution

There are different solutions. Let's look at the simplest. The first solution would be to use the `ngxsAfterBootstrap` method:

```ts
@State<string | null>({
  name: 'version',
  defaults: null
})
@Injectable()
export class VersionState implements NgxsAfterBootstrap {
  private configService = inject(ConfigService);

  ngxsAfterBootstrap(ctx: StateContext<string | null>) {
    ctx.setState(this.configService.getVersion());
  }
}
```

The second solution would be dispatching some `SetVersion` action right after the version is fetched:

```ts
export class SetVersion {
  static readonly type = '[Version] Set version';

  constructor(public version: string) {}
}

@State<string | null>({
  name: 'version',
  defaults: null
})
@Injectable()
export class VersionState {
  @Action(SetVersion)
  setVersion(ctx: StateContext<string | null>, action: SetVersion): void {
    ctx.setState(action.version);
  }
}

@Injectable({ providedIn: 'root' })
export class ConfigService {
  private http = inject(HttpClient);
  private store = inject(Store);

  loadVersion() {
    return this.http.get<string>('/api/version').pipe(
      tap(version => {
        this.store.dispatch(new SetVersion(version));
      })
    );
  }
}
```

### Summary

In conclusion, the `ngxsOnInit` method is useful when you need to set some calculated values on the state with access to dependency injection within the state class, but before the app is bootstrapped. This allows components to pick up available data.


# Composition

You can compose multiple stores together using class inheritance. This is quite simple:

```ts
@State({
  name: 'zoo',
  defaults: {
    type: null
  }
})
@Injectable()
class ZooState {
  @Action(Eat)
  eat(ctx: StateContext) {
    ctx.setState({ type: 'eat' });
  }
}

@State({
  name: 'stlzoo'
})
@Injectable()
class StLouisZooState extends ZooState {
  @Action(Drink)
  drink(ctx: StateContext) {
    ctx.setState({ type: 'drink' });
  }
}
```

Now when `StLouisZooState` is invoked, it will share the actions of the `ZooState`. Also all state options are inherited.


# Lazy Loading

States can be easily lazy-loaded by adding the `provideStates` function to the `Route` providers:

```ts
import { provideStates } from '@ngxs/store';

export const routes: Routes = [
  {
    path: '',
    component: AnimalsComponent,
    providers: [provideStates([AnimalsState])]
  }
];
```

If you are still using modules, you can import the `NgxsModule` using the `forFeature` method:

```ts
@NgModule({
  imports: [NgxsModule.forFeature([AnimalsState])]
})
export class LazyModule {}
```

It's important to note that when lazy-loading a state, it is registered in the global state, meaning this state object will now be persisted globally. Even though it's available globally, you should only use it within that feature component to ensure you don't create dependencies on things that may not be loaded yet.

How are feature states added to the global state graph? Assume you have a `ZoosState`:

```ts
@State<Zoo[]>({
  name: 'zoos',
  defaults: []
})
@Injectable()
export class ZoosState {}
```

And it's registered at the root level via `provideStore([ZoosState])`. Assume you've got a feature `offices` state:

```ts
@State<Office[]>({
  name: 'offices',
  defaults: []
})
@Injectable()
export class OfficesState {}
```

After the route is loaded and its providers are initialized, the global state will have the following signature if you register this state in some lazy-loaded component via `provideStates([OfficesState])`:

```ts
{
  zoos: [],
  offices: []
}
```

You can try it yourself by invoking `store.snapshot()` and printing the result to the console before and after the lazy component is loaded.

## `lazyProvider`

The `lazyProvider` function is designed to defer the registration of Angular providers until they are explicitly needed — such as when navigating to a route or triggering a guard. This is particularly useful for feature state libraries, where including providers in multiple locations could cause them to be unintentionally bundled into the initial application bundle.

```ts
import { lazyProvider } from '@ngxs/store';

const routes = [
  {
    path: 'home',
    loadComponent: () => import('./home/home.component').then(m => m.HomeComponent),
    canActivate: [
      lazyProvider(async () => (await import('path-to-state-library')).invoicesStateProvider)
    ]
  }
];
```

Exporting a provider:

```ts
// path-to-state-library/index.ts
export const invoicesStateProvider = provideStates([InvoicesState]);
```

It also supports `default` exports, which are common in dynamically imported ES modules. If the imported provider is wrapped in a default property (e.g., `export default invoicesStateProvider`), the function will automatically unwrap and register it.

```ts
// In routes
lazyProvider(() => import('path-to-state-library'));

// path-to-state-library/index.ts
const invoicesStateProvider = provideStates([InvoicesState]);
export default invoicesStateProvider;
```


# State Operators

## State Operators

### Why?

The NGXS `patchState` method is used to do [immutable object](https://en.wikipedia.org/wiki/Immutable_object) updates to the container state slice without the typical long-handed syntax. This is very neat and convenient because you do not have to use the `getState` and `setState` as well as the `Object.assign(...)`or the spread operator to update the state. The `patchState` method only offers a shallow patch and as a result is left wanting in more advanced scenarios. This is where state operators come in. The `setState` method can be passed a state operator which will be used to determine the new state.

### Basic

The basic idea of operators is that we could describe the modifications to the state using curried functions that are given any inputs that they need to describe the change and are finalized using the state slice that they are assigned to.

## Example

From theory to practice - let's take the following example:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch } from '@ngxs/store/operators';

export interface AnimalsStateModel {
  zebras: string[];
  pandas: string[];
  monkeys?: string[];
}

export class CreateMonkeys {
  static readonly type = '[Animals] Create monkeys';
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: {
    zebras: [],
    pandas: []
  }
})
@Injectable()
export class AnimalsState {
  @Action(CreateMonkeys)
  createMonkeys(ctx: StateContext<AnimalsStateModel>) {
    ctx.setState(
      patch<AnimalsStateModel>({
        monkeys: []
      })
    );
  }
}
```

The `patch` operator expresses the intended modification quite nicely and returns a function that will apply these modifications as a new object based on the provided state. In order to understand what this is doing let's express this in a long handed form:

```ts
  // For demonstration purposes! This long handed form is not needed from NGXS v3.4 onwards.
  @Action(CreateMonkeys)
  createMonkeys(ctx: StateContext<AnimalsStateModel>) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      monkeys: []
    });
  }
```

### Supplied State Operators

This is not the only operator, we introduce much more that can be used along with or in place of `patch`.

If the state slice you're patching might be `null` or `undefined`, regular `patch` will throw because it tries to spread a non-object. `safePatch` handles that case by treating a missing state as an empty object `{}` before applying the patch:

```ts
safePatch<T extends object>(patchSpec: PatchSpec<T>): StateOperator<T>
```

This is handy when a slice of state is optional and may not have been initialized yet. For example:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, safePatch } from '@ngxs/store/operators';

export interface UserPreferences {
  theme: string;
  language: string;
}

export interface UserStateModel {
  name: string;
  preferences: UserPreferences | null;
}

export class SetTheme {
  static readonly type = '[User] Set theme';
  constructor(public theme: string) {}
}

@State<UserStateModel>({
  name: 'user',
  defaults: {
    name: '',
    preferences: null
  }
})
@Injectable()
export class UserState {
  @Action(SetTheme)
  setTheme(ctx: StateContext<UserStateModel>, action: SetTheme) {
    ctx.setState(
      patch<UserStateModel>({
        // safePatch handles preferences being null — no need to initialize it first
        preferences: safePatch<UserPreferences>({ theme: action.theme })
      })
    );
  }
}
```

With plain `patch`, the action above would fail if `preferences` is `null`. With `safePatch`, it treats `null` as `{}` and produces `{ theme: 'dark', language: undefined }` — or whatever the patch spec describes. This also works when nesting `safePatch` inside itself for deeply optional structures.

If you want to update the value of a property based on some condition - you can use `iif`, it's signature is:

```ts
iif<T>(
  condition: Predicate<T> | boolean,
  trueOperatorOrValue: StateOperator<T> | T,
  elseOperatorOrValue?: StateOperator<T> | T
): StateOperator<T>
```

If you want to update an item in the array using an operator or value - you can use `updateItem`, it's signature is:

```ts
updateItem<T>(selector: number | Predicate<T>, operator: T | StateOperator<T>): StateOperator<T[]>
```

If you want to update **all** items in the array that match a predicate - use `updateItems`. Unlike `updateItem`, which stops at the first match, `updateItems` walks the entire array and applies the operator or value to every matching element:

```ts
updateItems<T>(selector: Predicate<T>, operator: T | StateOperator<T>): StateOperator<T[]>
```

For example, to mark every inactive animal as active in one `setState` call:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, updateItems } from '@ngxs/store/operators';

export interface Animal {
  name: string;
  active: boolean;
}

export interface AnimalsStateModel {
  animals: Animal[];
}

export class ActivateAll {
  static readonly type = '[Animals] Activate all';
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: { animals: [] }
})
@Injectable()
export class AnimalsState {
  @Action(ActivateAll)
  activateAll(ctx: StateContext<AnimalsStateModel>) {
    ctx.setState(
      patch<AnimalsStateModel>({
        animals: updateItems<Animal>(animal => !animal.active, patch({ active: true }))
      })
    );
  }
}
```

If you want to remove an item from an array by index or predicate - you can use `removeItem`:

```ts
removeItem<T>(selector: number | Predicate<T>): StateOperator<T[]>
```

If you want to remove **all** items in the array that match a predicate - use `removeItems`. Unlike `removeItem`, which stops at the first match, `removeItems` walks the entire array and drops every qualifying element:

```ts
removeItems<T>(selector: Predicate<T>): StateOperator<T[]>
```

For example, to purge all inactive animals in one `setState` call:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, removeItems } from '@ngxs/store/operators';

export interface Animal {
  name: string;
  active: boolean;
}

export interface AnimalsStateModel {
  animals: Animal[];
}

export class PurgeInactive {
  static readonly type = '[Animals] Purge inactive';
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: { animals: [] }
})
@Injectable()
export class AnimalsState {
  @Action(PurgeInactive)
  purgeInactive(ctx: StateContext<AnimalsStateModel>) {
    ctx.setState(
      patch<AnimalsStateModel>({
        animals: removeItems<Animal>(animal => !animal.active)
      })
    );
  }
}
```

If you want to insert an item to an array, optionally before a specified index - use `insertItem` operator:

```ts
insertItem<T>(value: T, beforePosition?: number): StateOperator<T[]>
```

If you want to append specified items to the end of an array - the `append` operator is suitable for that:

```ts
append<T>(items: T[]): StateOperator<T[]>
```

It's also possible to compose multiple operators into a single operator that would apply each consecutively using `compose`:

```ts
compose<T>(...operators: StateOperator<T>[]): StateOperator<T>
```

These operators introduce a new way of declarative state mutation.

### Advanced Example

Let's look at more advanced examples:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, append, removeItem, insertItem, updateItem } from '@ngxs/store/operators';

export interface AnimalsStateModel {
  zebras: string[];
  pandas: string[];
}

export class AddZebra {
  static readonly type = '[Animals] Add zebra';
  constructor(public payload: string) {}
}

export class RemovePanda {
  static readonly type = '[Animals] Remove panda';
  constructor(public payload: string) {}
}

export class ChangePandaName {
  static readonly type = '[Animals] Change panda name';
  constructor(public payload: { name: string; newName: string }) {}
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: {
    zebras: ['Jimmy', 'Jake', 'Alan'],
    pandas: ['Michael', 'John']
  }
})
@Injectable()
export class AnimalsState {
  @Action(AddZebra)
  addZebra(ctx: StateContext<AnimalsStateModel>, action: AddZebra) {
    ctx.setState(
      patch<AnimalsStateModel>({
        zebras: append<string>([action.payload])
      })
    );
  }

  @Action(RemovePanda)
  removePanda(ctx: StateContext<AnimalsStateModel>, action: RemovePanda) {
    ctx.setState(
      patch<AnimalsStateModel>({
        pandas: removeItem<string>(name => name === action.payload)
      })
    );
  }

  @Action(ChangePandaName)
  changePandaName(ctx: StateContext<AnimalsStateModel>, action: ChangePandaName) {
    ctx.setState(
      patch<AnimalsStateModel>({
        pandas: updateItem<string>(
          name => name === action.payload.name,
          action.payload.newName
        )
      })
    );
  }
}
```

You will see that in each case above the state operators are wrapped within a call to the `patch` operator. This is only done because of the convenience that the `patch` state operator provides for targeting a nested property of the state.

### Typing Operators

Specifying types for the `patch` operator is always necessary when doing nested updates. You can face cases when the `patch` operator cannot infer the nested type structure. Let's look at the following state:

```ts
export class UpdateLine1 {
  static readonly type = '[Address] Update line1';
  constructor(readonly line1: string) {}
}

export interface AddressStateModel {
  country: {
    city: {
      address: {
        line1: string;
      };
    };
  };
}

@State<AddressStateModel>({
  name: 'address',
  defaults: {
    country: {
      city: {
        address: {
          line1: ''
        }
      }
    }
  }
})
@Injectable()
export class AddressState {
  @Action(UpdateLine1)
  updateLine1(ctx: StateContext<AddressStateModel>, action: UpdateLine1) {
    ctx.setState(
      patch({
        country: patch({
          city: patch({
            address: patch({
              line1: action.line1
            })
          })
        })
      })
    );
  }
}
```

If we don't specify the type explicitly for `patch`, all objects are inferred as `unknown`, meaning that TypeScript cannot tell us that we're doing something wrong or using the wrong type. The correct way of specifying nested types is shown below:

```ts
export class UserState {
  @Action(UpdateLine1)
  updateLine1(ctx: StateContext<AddressStateModel>, action: UpdateLine1) {
    ctx.setState(
      patch<AddressStateModel>({
        country: patch<AddressStateModel['country']>({
          city: patch<AddressStateModel['country']['city']>({
            address: patch<AddressStateModel['country']['city']['address']>({
              line1: action.line1
            })
          })
        })
      })
    );
  }
}
```

If we change `country` to `Qcountry` (intentional mistake), the compiler will tell us `Object literal may only specify known properties, but 'Qcountry' does not exist`. The same technique may be used with other operators if they cannot infer the type.

💡 Tip: we can specify the state model type and chain properties to get the desired type. Like in the example above.

### Custom Operators

You can also define your own operators for updates that are common to your domain. For example:

```ts
function addEntity(entity: Entity): StateOperator<EntitiesStateModel> {
  return (state: Readonly<EntitiesStateModel>) => {
    return {
      ...state,
      entities: { ...state.entities, [entity.id]: entity },
      ids: [...state.ids, entity.id]
    };
  };
}

interface CitiesStateModel {
  // ...
}

@State<CitiesStateModel>({
  name: 'cities',
  defaults: {
    entities: {},
    ids: []
  }
})
@Injectable()
export class CitiesState {
  @Action(AddCity)
  addCity(ctx: StateContext<CitiesStateModel>, action: AddCity) {
    ctx.setState(addEntity<CitiesStateModel>(action.payload.city));
  }
}
```

Here you can see that the developer chose to define a convenience method called `addEntity` for doing a common state modification. This operator could also have also been defined using existing operators like so:

```ts
function addEntity(entity: Entity): StateOperator<EntitiesStateModel> {
  return patch<EntitiesStateModel>({
    entities: patch({ [entity.id]: entity }),
    ids: append([entity.id])
  });
}
```

As you can see, state operators are very powerful to start moving your immutable state updates to be more declarative and expressive. Enhancing the overall maintainability and readability of your state class code.

### Snippets

Check this [section](/concepts/state/operators-1) for more operators that you can add to your application.

### Relevant Articles

[NGXS State Operators](https://medium.com/ngxs/ngxs-state-operators-8b339641b220)


# Custom State Operators

In this section you will find state operators that are not part of the library but can be very helpful in your app.

## upsertItem

Inserts or updates an item in an array depending on whether it exists.

### Usage

```ts
ctx.setState(
  patch<FoodModel>({
    foods: upsertItem<Food>(f => f.id === foodId, food)
  })
);
```

### State Operator Code

```ts
import { StateOperator } from '@ngxs/store';
import {
  compose,
  iif,
  insertItem,
  NoInfer,
  patch,
  Predicate,
  updateItem
} from '@ngxs/store/operators';

export function upsertItem<T>(
  selector: number | Predicate<T>,
  upsertValue: NoInfer<T>
): StateOperator<T[]> {
  return compose<T[]>(
    items => <T[]>(items || []),
    iif<T[]>(
      items => Number(selector) === selector,
      iif<T[]>(
        items => selector < items.length,
        updateItem(selector, patch(upsertValue)),
        insertItem(upsertValue, <number>selector)
      ),
      iif<T[]>(
        items => items.some(<Predicate<T>>selector),
        updateItem(selector, patch(upsertValue)),
        insertItem(upsertValue)
      )
    )
  );
}
```

### Collaborate with your awesome operator!

Have you identified an use case for a new operator? If that's the case you can collaborate sharing it here! To learn more read this [issue](https://github.com/ngxs/store/issues/926) and submit your PR with your operator as part of the *Snippets* section.


# Shared State

Shared state is the ability to get state from one state container and use its properties in another state container in a read-only manner. While it's not natively supported it can be accomplished.

Let's say you have 2 stores: Animals and Preferences. In your preferences store, which is backed by `localstorage`, you have the sort order for the Animals. You need to get the state from the preferences in order to be able to sort your animals. This is achievable with `selectSnapshot`.

```ts
@State<PreferencesStateModel>({
  name: 'preferences',
  defaults: {
    sort: [{ prop: 'name', dir: 'asc' }]
  }
})
@Injectable()
export class PreferencesState {
  @Selector()
  static getSort(state: PreferencesStateModel) {
    return state.sort;
  }
}

@State<AnimalStateModel>({
  name: 'animals',
  defaults: [
    animals: []
  ]
})
@Injectable()
export class AnimalState {

  constructor(private store: Store) {}

  @Action(GetAnimals)
  getAnimals(ctx: StateContext<AnimalStateModel>) {
    const state = ctx.getState();

    // select the snapshot state from preferences
    const sort = this.store.selectSnapshot(PreferencesState.getSort);

    // do sort magic here
    return state.sort(sort);
  }

}
```


# State Token

A state token can be used as a representation of a state class without referring directly to the state class itself. When creating an StateToken you will provide the location that the state should be stored on your state tree. You can also set a default state model type of the parameterized type `T`, which can assist with ensuring the type safety of referring to your state in your application. The state token is declared as follows:

```ts
import { StateToken } from '@ngxs/store';

const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');
```

Or if you choose to not expose the model of your state class to the rest of the application then you can pass the type as `unknown` or `any` (this is useful if you want to keep all knowledge of the structure of your state class model private).

```ts
const TODOS_STATE_TOKEN = new StateToken<unknown>('todos');
```

If you use pass this token as the `name` property in your `@State` declaration (or if the path specified matches your `name` property then you can use this token to refer to this state class from other parts of your application (in your selectors, or in plugins like the storage plugin that need to refer to a state class). The token can be used in your `@State` declaration as follows:

```ts
export interface TodoStateModel {
  title: string;
  completed: boolean;
}

export const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');

// Note: the @State model type is inferred from in your token.
@State({
  name: TODOS_STATE_TOKEN,
  defaults: []
})
@Injectable()
export class TodosState {
  // ...
}
```

A state token with a model type provided can be used in other parts of your application to improve type safety in the following aspects:

* Improved type checking for `@State`, `@Selector` in a state class

```ts
export interface TodoStateModel {
  title: string;
  completed: boolean;
}

export const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');

@State({
  name: TODOS_STATE_TOKEN,
  defaults: [] // if you specify the wrong state type, will be a compilation error
})
@Injectable()
export class TodosState {
  @Selector([TODOS_STATE_TOKEN]) // if you specify the wrong state type, will be a compilation error
  static getCompletedList(state: TodoStateModel[]): TodoStateModel[] {
    return state.filter(todo => todo.completed);
  }
}
```

The following code demonstrates mismatched types that will be picked up as compilation errors:

```ts
export const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');

@State({
  name: TODOS_STATE_TOKEN,
  defaults: {} // compilation error - array was expected, inferred from the token type
})
@Injectable()
export class TodosState {
  @Selector([TODOS_STATE_TOKEN]) // compilation error - TodoStateModel[] does not match string[]
  static getCompletedList(state: string[]): string[] {
    return state;
  }
}
```

* Improved type inference for `store.selectSignal, store.select, store.selectOnce, store.selectSnapshot`

```ts
@Component(/**/)
class AppComponent implements OnInit {
  constructor(private store: Store) {}

  ngOnInit(): void {
    const todosSignal = this.store.selectSignal(TODOS_STATE_TOKEN); // infers type Signal<TodoStateModel[]>
    const todos = this.store.selectSnaphot(TODOS_STATE_TOKEN); // infers type TodoStateModel[]
    const todos$ = this.store.select(TODOS_STATE_TOKEN); // infers type Observable<TodoStateModel[]>
    const oneTodos$ = this.store.selectOnce(TODOS_STATE_TOKEN); // infers type Observable<TodoStateModel[]>
  }
}
```


# Immutability Helpers

Redux is a tiny pattern that represents states as immutable objects. Redux was originally designed for React. Most Redux concepts, such as pure functions, are centered around the React ecosystem. Nowadays Redux is not directly related to React.

The cornerstone of Redux is immutability. Immutability is an amazing pattern to minimise unpredictable behaviour in our code. We're not going to cover functional programming in this article. However we're going to look at very useful packages that are called "immutability helpers".

## The Problem

Most developers have to deal with, so called, "deep objects" and most important follow the immutability concept, when it comes to changing the value of some deeply nested property. Given the following code:

```ts
export interface Task {
  title: string;
  dates: {
    startDate: string;
    dueDate: string;
  };
}

export interface TrelloStateModel {
  tasks: {
    [taskId: string]: Task;
  };
}
@State<TrelloStateModel>({
  name: 'trello',
  defaults: {
    tasks: {}
  }
})
@Injectable()
export class TrelloState {}
```

Let's imagine that we're faced with the task of changing the `dueDate` property:

```ts
export class UpdateDueDate {
  static readonly type = '[Trello] Update due date';
  constructor(
    public taskId: string,
    public dueDate: string
  ) {}
}
```

Let's see how we would implement the `updateDueDate` action handler:

```ts
export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    ctx.setState(state => ({
      tasks: {
        ...state.tasks,
        [action.taskId]: {
          ...state.tasks[action.taskId],
          dates: {
            ...state.tasks[action.taskId].dates,
            dueDate: action.dueDate
          }
        }
      }
    }));
  }
}
```

This code will work but unfortunately it is complicated to maintain and understand. It's not self-descriptive and will be daunting for new developers.

## Solutions

There are different ways to improve this code. Let us look at a few different packages that can help in this regard.

### State Operators

[State operators](/concepts/state/operators) are first-class immutability helpers that NGXS provides out of the box. The `patch` operator will become your best friend in case of choosing state operators as your immutability helpers. Let's see how we could re-write the above code with the help of the `patch` state operator:

```ts
import { patch } from '@ngxs/store/operators';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    ctx.setState(
      patch({
        tasks: patch({
          [action.taskId]: patch({
            dates: patch({
              dueDate: action.dueDate
            })
          })
        })
      })
    );
  }
}
```

### immer

`immer` is a very popular library that allows you to make changes to immutable objects as if they were mutable. The below code shows how to write the same code with the help of Immer:

```ts
import { produce } from 'immer';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = produce(ctx.getState(), draft => {
      draft.tasks[action.taskId].dates.dueDate = action.dueDate;
    });

    ctx.setState(state);
  }
}
```

Immer's `produce` function can be also used as a state operator:

```ts
import { produce } from 'immer';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    ctx.setState(
      produce(draft => {
        draft.tasks[action.taskId].dates.dueDate = action.dueDate;
      })
    );
  }
}
```

You may notice how much less code this is and how much better it looks. From the `immer` repository:

> Using Immer is like having a personal assistant; he takes a letter (the current state) and gives you a copy (draft) to jot changes onto. Once you are done, the assistant will take your draft and produce the real immutable, final letter for you (the next state).

[Immer repository](https://github.com/immerjs/immer)

### immutability-helper

`immutability-helper` is a small package that lets you mutate a copy of data without changing the original source:

```ts
import update from 'immutability-helper';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = update(ctx.getState(), {
      tasks: {
        [action.taskId]: {
          dates: {
            dueDate: {
              $set: action.dueDate
            }
          }
        }
      }
    });

    ctx.setState(state);
  }
}
```

[immutability-helper repository](https://github.com/kolodny/immutability-helper)

### object-path-immutable

`object-path-immutable` is a small library that allows you to modify deep object properties without modifying the original object. Let's look at how we could write the same code using this library:

```ts
import immutable from 'object-path-immutable';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = immutable.set(
      ctx.getState(),
      `tasks.${action.taskId}.dates.dueDate`,
      action.dueDate
    );

    ctx.setState(state);
  }
}
```

[object-path-immutable repository](https://github.com/mariocasciaro/object-path-immutable)

### immutable-assign

`immutable-assign` is a lightweight library that pursues the same goal. Its syntax is similar to `immer`'s:

```ts
import * as iassign from 'immutable-assign';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = iassign(ctx.getState(), state => {
      state.tasks[action.taskId].dates.dueDate = action.dueDate;
      return state;
    });

    ctx.setState(state);
  }
}
```

[immutable-assign repository](https://github.com/engineforce/ImmutableAssign)

### Ramda

Ramda is a great library for functional programming and it is used in a large number of projects. This example might be useful for people who use both Ramda and NGXS in their projects:

```ts
import * as R from 'ramda';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const property = R.lensPath(['tasks', action.taskId, 'dates', 'dueDate']);
    const state = R.set(property, action.dueDate, ctx.getState());
    ctx.setState(state);
  }
}
```

[Ramda repository](https://github.com/ramda/ramda)

### icepick

`icepick` is a zero-dependency library for working with immutable collections. Given the following re-written code:

```ts
import * as icepick from 'icepick';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = icepick.setIn(
      ctx.getState(),
      ['tasks', action.taskId, 'dates', 'dueDate'],
      action.dueDate
    );

    ctx.setState(state);
  }
}
```

[icepick repository](https://github.com/aearly/icepick)

## Summary

We have looked at several different libraries that might be helpful in accompanying the concept of immutability. Choose the right one for your needs.


# Error Handling


# Sub States

{% hint style="danger" %}
**DEPRECATED**

[Find out why we are deprecating the sub states](/deprecations/sub-states-deprecation)
{% endhint %}

Complex and large state graphs are difficult to manage. Oftentimes we need to break these down into sub states that we can manage on a individual basis. With NGXS, we can use a concept called sub states to handle this.

## Unidirectional Data Flow in NGXS

Unidirectional data flow as a pattern is usually mentioned when talking about performance in Angular. The reason why data flows from top to bottom, is because change detection is also always performed from top to bottom for every single component, every single time, starting from the root component. Unidirectional data flow is much easier to debug as it has no side effects unlike the AngularJS's digest cycle. The view is stable throughout a single rendering pass.

Unidirectional data flow policy is also applied to the state management. We have to make sure that states are independent and do not affect each other, the child state should know nothing about its parent. Potentially that could lead to unpredictable side effects. Our states are meant to be encapsulated from each other and only the parent can manage its children.

<figure><img src="/files/g7dt3pZOGcxek8nXxQNT" alt=""><figcaption><p>Unidirectional</p></figcaption></figure>

## Example

Let's take the following example state graph:

```ts
{
  cart: {
    checkedout: false,
    items: [],
    saved: {
      dateSaved: new Date(),
      items: []
    };
  }
}
```

At the top, we have a `cart` with several items associated to its state. Beneath that we have a `saved` object which represents another state slice. To express this relationship with NGXS, we simply need to use the `children` property in the `@State` decorator:

```ts
export interface CartStateModel {
  checkedout: boolean;
  items: CartItem[];
}

@State<CartStateModel>({
  name: 'cart',
  defaults: {
    checkedout: false,
    items: []
  },
  children: [CartSavedState]
})
@Injectable()
export class CartState {}
```

Then we describe our sub-state like normal:

```ts
export interface CartSavedStateModel {
  dateSaved: Date;
  items: CartItem[];
}

@State<CartSavedStateModel>({
  name: 'saved',
  defaults: {
    dateSaved: new Date(),
    items: []
  }
})
@Injectable()
export class CartSavedState {}
```

The relationship between these two are bound by their hierarchical order. To finish this up, we need to import both of these into the `NgxsModule`:

```ts
@NgModule({
  imports: [NgxsModule.forRoot([CartState, CartSavedState])]
})
export class AppModule {}
```

The store will then automatically recognize the relationship and bind them together.

## Caveats

This is only intended to work with nested objects, so trying to create stores on nested array objects will not work.

Sub states can only be used once, reuse implies several restrictions that would eliminate some high value features. If you want to re-use them, just create a new state and inherit from it.

## Preventing sub-state erasure

Let's have a look at the state graph again:

```ts
{
  cart: {
    checkedout: false,
    items: [],
    saved: {
      dateSaved: new Date(),
      items: []
    };
  }
}
```

This means that you have to avoid using `setState` function in the parent `CartState` state as your child state will erase. Assume you've got an action called `SetCheckedoutAndItems`:

```ts
export interface CartStateModel {
  checkedout: boolean;
  items: CartItem[];
}

export class SetCheckedoutAndItems {
  static type = '[Cart] Set checkedout and items';
  constructor(
    public checkedout: boolean,
    public items: CartItem[]
  ) {}
}

@State<CartStateModel>({
  name: 'cart',
  defaults: {
    checkedout: false,
    items: []
  },
  children: [CartSavedState]
})
@Injectable()
export class CartState {
  @Action(SetCheckedoutAndItems)
  setCheckedoutAndItems(
    ctx: StateContext<CartStateModel>,
    { checkedout, items }: SetCheckedoutAndItems
  ): void {
    ctx.patchState({ checkedout, items });
  }
}
```

If we had used the `setState` function - we would have overwritten the whole state value and our sub-state `CartSavedState` would be erased. The `patchState` function allows us to update only needed properties and preserve our sub-state safe and sound.


# SELECT

Selects are functions that slice a specific portion of state from the global state container.

In CQRS and Redux patterns, we maintain a separation between READ and WRITE operations. This pattern is also present in NGXS. When we need to retrieve data from our store, we utilize a select operator to access this data.

In NGXS, the `Store` service provides multiple methods for selecting state.

## Store Select Function

The `Store` class also has a `select` function:

```ts
import { Store } from '@ngxs/store';
import { Observable } from 'rxjs';

@Component({ ... })
export class ZooComponent {
  animals$: Observable<string[]> = this.store.select(ZooState.getAnimals);

  constructor(private store: Store) {}
}
```

There is also a `selectOnce` that will basically do `select().pipe(take(1))` for you automatically as a shortcut method.

This can be useful in route guards where you only want to check the current state and not continue watching the stream. It can also be useful for unit testing.

## Store Select Signal Function

The `Store` can return a signal instead of an observable:

```ts
import { Signal } from '@angular/core';
import { Store } from '@ngxs/store';

@Component({
  selector: 'app-zoo',
  template: `
    @for (panda of pandas(); track $index) {
      <p>{{ panda }}</p>
    }
  `
})
export class ZooComponent {
  pandas: Signal<string[]> = this.store.selectSignal(ZooState.getPandas);

  constructor(private store: Store) {}
}
```

The `selectSignal` function only accepts a 'typed' selector function (a function that carries type information) and a state token. There is no option to provide an anonymous function as demonstrated in the previous example with `this.store.select(state => state.zoo.animals)`.

We don't allow any options to be provided to the internal `computed` function, such as an equality function, because immutability is a fundamental premise for the existence of data in our state. Users should never have a reason to specify the equality comparison function.

## Snapshot Selects

On the store, there is a `selectSnapshot` function that allows you to pull out the raw value. This is helpful for cases where you need to get a static value but can't use Observables. A good use case for this would be an interceptor that needs to get the token from the auth state.

```ts
@Injectable()
export class JWTInterceptor implements HttpInterceptor {
  constructor(private store: Store) {}

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    const token = this.store.selectSnapshot<string>(AuthState.getToken);

    req = req.clone({
      setHeaders: {
        Authorization: `Bearer ${token}`
      }
    });

    return next.handle(req);
  }
}
```

## Memoized Selectors

There are two distinct roles in NGXS selectors: **defining** selectors with `@Selector` and **consuming** them in components and services via `store.select()`, `store.selectSignal()`, or `store.selectSnapshot()`.

The `@Selector` decorator defines a memoized, reusable selector function. It is placed on `static` methods and can live in a state class, a dedicated query class (see [Meta Selectors](#meta-selectors) below), or any plain class. Keeping selectors outside component classes is recommended so they remain reusable and independently testable. Components and services consume those selectors using the `store.select*` methods shown above — they do not define them.

Selectors defined with `@Selector` are memoized: they recalculate only when their input arguments change, and the cached result is shared across all consumers.

Let's create a selector that will return a list of pandas from the animals.

```ts
import { Injectable } from '@angular/core';
import { State, Selector } from '@ngxs/store';

@State<string[]>({
  name: 'animals',
  defaults: []
})
@Injectable()
export class ZooState {
  @Selector()
  static getPandas(state: string[]) {
    return state.filter(s => s.indexOf('panda') > -1);
  }
}
```

Notice, the `state` is just the local state for this `ZooState` class. Now in our component, we simply do:

```ts
@Component({ ... })
export class AppComponent {
  pandas = this.store.selectSignal(ZooState.getPandas);

  constructor(private store: Store) {}
}
```

And our `pandas` will only return animals with the name panda in them.

### Selector Options

The behavior of the memoized selectors can be configured at a global level using the `selectorOptions` property in the options passed to the `provideStore` or `NgxsModule.forRoot` call (see [Options](/concepts/store/options)).\
These options can also be provided through the `@SelectorOptions` decorator at a Class or Method level in order to configure the behavior of selectors within that scope. The following options are available:

#### `suppressErrors`

* `true` will cause any error within a selector to result in the selector returning `undefined`.
* `false` results in these errors propagating through the stack that triggered the evaluation of the selector that caused the error.

#### `injectContainerState` ([TO BE DEPRECATED](/deprecations/inject-container-state-deprecation))

> ⚠️ This property is only useful for incrementally migrating codebases from NGXS v3 to versions after v3. It is not recommended to keep it set to `true`. In versions after v3, users should have no reason to set this property explicitly.

* `true` will cause all selectors defined within a state class to receive the container class' state model as their first parameter. As a result every selector would be re-evaluated after any change to that state (**this should only be used during migrations**).
* `false` will prevent the injection of the container state model as the first parameter of a selector method (defined within a state class) that joins to other selectors for its parameters (**this is the default value now**).
* See the linked deprecation notice for a detailed explanation of the effects of this setting.

### Memoized Selectors with Arguments

Selectors can be configured to accept arguments.\
There are two patterns that allow for this: [Lazy Selectors](#lazy-selectors) or [Dynamic Selectors](#dynamic-selectors)

#### Lazy Selectors

To create a lazy selector all that you need to do is return a function from the selector. The function returned by the selector will be memoized automatically and the logic inside this function will be evaluated at a later stage when the consumer of the selector executes the function. Note that this function can take any number of arguments (or zero arguments) as it is the consumer's responsibility to supply them.

For instance, I can have a Lazy Selector that will filter my pandas to the provided type of panda.

```ts
@State<string[]>({
  name: 'animals',
  defaults: []
})
@Injectable()
export class ZooState {
  @Selector()
  static getPandas(state: string[]) {
    return (type: string) => {
      return state.filter(s => s.indexOf('panda') > -1).filter(s => s.indexOf(type) > -1);
    };
  }
}
```

Then you can use `store.selectSignal` and evaluate the lazy function using the `computed`:

```ts
import { computed } from '@angular/core';
import { Store } from '@ngxs/store';
import { map } from 'rxjs';

@Component({ ... })
export class ZooComponent {
  pandas = this.store.selectSignal(ZooState.getPandas);

  babyPandas = computed(() => {
    const filterFn = this.pandas();
    return filterFn('baby');
  });

  constructor(private store: Store) {}
}
```

#### Dynamic Selectors

A dynamic selector is created by using the `createSelector` function as opposed to the `@Selector` decorator. It does not need to be created in any special area at any specific time. The typical use case though would be to create a selector that looks like a normal selector but takes an argument to provide to the dynamic selector.

For instance, I can have a Dynamic Selector that will filter my pandas to the provided type of panda:

```ts
@State<string[]>({
  name: 'animals',
  defaults: []
})
@Injectable()
export class ZooState {
  static getPandas(type: string) {
    return createSelector([ZooState], (state: string[]) => {
      return state.filter(s => s.indexOf('panda') > -1).filter(s => s.indexOf(type) > -1);
    });
  }
}
```

Then you can use `selectSignal` to call this function with the parameter provided:

```ts
import { Store } from '@ngxs/store';
import { map } from 'rxjs';

@Component({ ... })
export class ZooComponent {
  babyPandas = this.store.selectSignal(ZooState.getPandas('baby'));

  adultPandas = this.store.selectSignal(ZooState.getPandas('adult'));

  constructor(private store: Store) {}
}
```

Note that each of these selectors have their own separate memoization. Even if two dynamic selectors created in this way are provided the same argument, they will have separate memoization.

These selectors are extremely powerful and are what is used under the hood to create all other selectors.

*Dynamic Selectors (dynamic state slice)*

An interesting use case would be to allow for a selector to be reused to select from States that have the same structure. For example:

```ts
export class SharedSelectors {
  static getEntities(stateClass) {
    return createSelector([stateClass], (state: { entities: any[] }) => {
      return state.entities;
    });
  }
}
```

Then this could be used as follows:

```ts
@Component({ ... })
export class ZooComponent {
  zoos = this.store.selectSignal(SharedSelectors.getEntities(ZooState));

  parks = this.store.selectSignal(SharedSelectors.getEntities(ParkState));

  constructor(private store: Store) {}
}
```

### Joining Selectors

When defining a selector, you can also pass other selectors into the signature of the `Selector` decorator to join other selectors with this state selector:

```ts
@State<PreferencesStateModel>({ ... })
@Injectable()
export class PreferencesState { ... }

@State<string[]>({ ... })
@Injectable()
export class ZooState {
  @Selector([ZooState, PreferencesState])
  static getFirstLocalPanda(state: string[], preferencesState: PreferencesStateModel) {
    return state.find(
      s => s.indexOf('panda') > -1 && s.indexOf(preferencesState.location)
    );
  }

  @Selector([ZooState.getFirstLocalPanda])
  static getHappyLocalPanda(panda: string) {
    return 'happy ' + panda;
  }

}
```

Please note that we have to explicitly pass the `ZooState` into the first selector since container states are not injected by default (unless you set `injectContainerState` to `true`).

The memoized selectors will recalculate when any of their input parameter values change (whether they use them or not). In the case of the behavior above where the state class's state model is injected as the first input parameter, the selectors will recalculate on any change to this model.

### Meta Selectors

By default selectors in NGXS are bound to a state. Sometimes you need the ability to join to un-related states in a high-performance re-usable fashion. A meta selector is a selector allows you to bind N number of selectors together to return a state stream.

Because `@Selector` works on any plain class — not only state classes — you can group related cross-cutting selectors into a dedicated query class. This is the recommended alternative to placing selectors in component classes:

```ts
export class CityQueries {
  @Selector([Zoo, ThemePark])
  static getZooThemeParks(zoos, themeParks) {
    return [...zoos, ...themeParks];
  }
}
```

Now we can use this `getZooThemeParks` selector anywhere in our application.

### The Order of Interacting Selectors

In versions of NGXS prior to 3.6.1 there was an issue where the order which the selectors were declared would matter. This was fixed in PR [#1514](https://github.com/ngxs/store/pull/1514) and selectors can now be declared in any arbitrary order.

### Inheriting Selectors

When we have states that share similar structure, we can extract the shared selectors into a base class which we can later extend from. If we have an `entities` field on multiple states, we can create a base class containing a dynamic `@Selector()` for that field, and extend from it on the `@State` classes like this.

```ts
export class EntitiesState {
  static getEntities<T>() {
    return createSelector([this], (state: { entities: T[] }) => {
      return state.entities;
    });
  }

  //...
}
```

And extend the `EntitiesState` class on each `@State` like this:

```ts
export interface UsersStateModel {
  entities: User[];
}

@State<UsersStateModel>({
  name: 'users',
  defaults: {
    entities: []
  }
})
@Injectable()
export class UsersState extends EntitiesState {
  //...
}

export interface ProductsStateModel {
  entities: Product[];
}

@State<ProductsStateModel>({
  name: 'products',
  defaults: {
    entities: []
  }
})
@Injectable()
export class ProductsState extends EntitiesState {
  //...
}
```

Then you can use them as follows:

```ts
@Component({ ... })
export class AppComponent {
  users = this.store.selectSignal(UsersState.getEntities<User>());

  products = this.store.selectSignal(ProductsState.getEntities<Product>());

  constructor(private store: Store) {}
}
```


# Mapped Sub States

NGXS provides the ability to merge multiple dynamic selectors into one.

Let's look at the code below:

```ts
interface Animal {
  type: string;
  age: string;
  name: string;
}

@State<Animal[]>({
  name: 'animals',
  defaults: [
    { type: 'zebra', age: 'old', name: 'Ponny' },
    { type: 'panda', age: 'young', name: 'Jimmy' }
  ]
})
@Injectable()
export class ZooState {
  static getPandas(age: string) {
    return createSelector([ZooState], (state: Animal[]) => {
      return state.filter(animal => animal.type === 'panda' && animal.age === age);
    });
  }

  static getZebras(age: string) {
    return createSelector([ZooState], (state: Animal[]) => {
      return state.filter(animal => animal.type === 'zebra' && animal.age === age);
    });
  }

  static getPandasAndZebras(age: string) {
    return createSelector(
      [ZooState.pandas(age), ZooState.zebras(age)],
      (pandas: Animal[], zebras: Animal[]) => {
        return [pandas, zebras];
      }
    );
  }
}
```

This construct will merge 2 dynamic selectors and memoize the result.

Another example could be multiple Zoos in our application:

```ts
interface Animal {
  type: string;
  age: string;
  name: string;
}

interface ZooStateModel {
  [id: string]: {
    animals: Animal[];
    ageFilter: string;
  };
}

@State<ZooStateModel>({
  name: 'animals',
  defaults: {
    zoo1: {
      ageFilter: 'young',
      animals: [
        { type: 'zebra', age: 'old', name: 'Ponny' },
        { type: 'panda', age: 'young', name: 'Jimmy' }
      ]
    }
  }
})
@Injectable()
export class ZooState {
  static getZooAnimals(zooName: string) {
    return createSelector([ZooState], (state: ZooStateModel) => state[zooName].animals);
  }

  static getPandas(zooName: string) {
    return createSelector([ZooState.getZooAnimals(zooName)], (state: Animal[]) => {
      return state.filter(animal => animal.type === 'panda' && animal.age === 'young');
    });
  }

  static getPandasWithoutMemoize(zooName: string) {
    return createSelector([ZooState], (state: ZooStateModel) => {
      return state[zooName].animals.filter(
        animal => animal.type === 'panda' && animal.age === 'young'
      );
    });
  }
}
```

In that example merging is required to avoid unnecessary store events. When we subscribe to `Zoo.getPandasWithoutMemoize` store will dispatch event whenever `ZooState` will change (even `ZooState.getAgeFilter`), but when subscribing to `Zoo.getPandas` store will dispatch event only if result has been changed.


# Optimizing Selectors

[Selectors](/concepts/select) are responsible for providing state data to your application. As your application code grows, naturally the number of selectors you create also increases. Ensuring your selectors are optimized can be instrumental in building a faster performing application.

## Memoization

Selectors are memoized functions. Memoized functions are calculated when their arguments change and the results are cached. Regardless of how many components or services consume a selector, a selector will calculate only once when state changes and the cached result will be returned to all consumers. Taking advantage of this feature can result in performance increases.

For example, there exists this state model:

```ts
interface SomeStateModel {
  data: Data[];
  name: string;
}
```

And in this example there is an input component where a user can type a name. On key down, an action is dispatched updating the `name` property of state. On the same page, another component renders `data`. In order to render state data we create a selector in our state class:

```ts
@Selector()
static getViewData(state: SomeStateModel) {
   return state.data.map(d => expensiveFunction(d));
}
```

Selectors defined in state classes implicitly have `state` injected as their first argument. The above selector will be recalculated every time the user types into the input component. Since `state` could update rapidly when a user types, the expensive selector will needlessly recalculate even though it does not care about the `name` property of `state` changing. This selector does not take advantage of memoization.

One way to solve this problem is to explicitly specify selector arguments using the `@Selector([...])` decorator. By default, the `injectContainerState` selector [option](/concepts/store/options) is `false`, which means the container state is **not** implicitly injected as the first argument for composite selectors defined within state classes. You must explicitly specify all arguments when using `@Selector([...])`. Any parameterless `@Selector()` decorators will still inject the state as an implicit argument. Note that this option does not apply to selectors declared *outside of state classes* (because there is no container state to inject). For example, we create two selectors in our state class:

```ts
@Selector([SomeState])
static getData(state: SomeStateModel) {
   return state.data;
}

@Selector([SomeState.getData])
static getViewData(data: Data[]) {
  return data.map(d => expensiveFunction(d));
}
```

This `getViewData` selector will not be recalculated when a user types into the input component. This selector targets the specific property of `state` it cares about as its argument by leveraging an additional selector. When the `name` property of state changes, the `getViewData` arguments *do not change*. Memoization is taken advantage of.

An alternative solution is to create a [meta selector](/concepts/select#meta-selectors). For example, we declare one selector in our state class and declare another selector outside of our state class:

```ts
@State({...})
@Injectable()
export class SomeState {
  @Selector()
  static getData(state: SomeStateModel) {
    return state.data;
  }
}

export class SomeStateQueries {
  @Selector([SomeState.getData])
  static getViewData(data: Data[]) {
    return data.map(d => expensiveFunction(d));
  }
}
```

## Implementation

Selectors are calculated when state changes. As your application grows, the number of state changes increases. Finding optimizations in your selector implementations can have significant benefits.

For example, say you have this state model:

```ts
interface SelectedDataStateModel {
  selectedIds: number[];
}
```

And you have this selector:

```ts
@Selector([SelectedDataState])
isDataSelected(state: SelectedDataStateModel) {
  return (id: number) => state.selectedIds.includes(id);
}
```

The above selector is an example of a [lazy selector](/concepts/select#lazy-selectors). This selector returns a function, which accepts an `id` as an argument and returns a boolean indicating whether or not this `id` is selected.

To consume this lazy selector in a component, use the standalone `select()` function, which calls `inject(Store).selectSignal` internally and returns a signal:

```ts
import { select } from '@ngxs/store';

@Component({
  selector: 'app-data-list',
  template: `
    @for (item of data(); track item.id) {
      <data-check-box [checked]="isDataSelected()(item.id)" />
    }
  `
})
export class DataListComponent {
  data = select(DataState.getData);
  isDataSelected = select(SelectedDataState.isDataSelected);
}
```

`isDataSelected` is a signal whose value is the filter function. In the template, `isDataSelected()` reads the signal and `(item.id)` invokes the returned function with the item's id.

The lazy selector returned by `isDataSelected` uses [Array.includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes) and has `O(n)` time complexity. When a user checks or unchecks an item, `state.selectedIds` is updated, therefore the `isDataSelected` selector is recalculated and the list must re-render. Every time the list re-renders, the lazy selector `isDataSelected` is invoked `data.length` number of times. Because the lazy selector implementation has `O(n)` time complexity, this template renders with `O(n^2)` time complexity - **Ugh!**. One magnitude of `n` for the length of `data`, another for `state.selectedIds.length`.

Here's one way to improve performance in that example:

```ts
@Selector([SelectedDataState])
isDataSelected(state: SelectedDataStateModel) {
  const selectedIds = new Set(state.selectedIds);
  return (id: number) => selectedIds.has(id);
}
```

The above selector implementation creates a [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set). The lazy selector returned by `isDataSelected` *is a closure with access to the `selectedIds` variable created in the parent function*. The lazy selector uses [Set.has](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set/has) which has `O(1)` time complexity.

Now when the list re-renders, because the lazy selector has `O(1)` time complexity, this template renders with `O(n)` time complexity. This optimizes performance by a magnitude of `n`.


# Type-Safe Selectors

NGXS v18+ pushes toward stronger type safety for selectors. The key challenge is that state classes do not carry their model type as part of the selector contract — when you pass a state class to `@Selector([MyState])` or `createSelector([MyState], ...)`, TypeScript cannot verify the annotated parameter type against the actual state model.

This page shows how to move from less type-safe patterns to fully type-safe ones, and introduces the selector utilities designed for this purpose.

## The Problem with State Classes as Selectors

When you write:

```ts
@Selector([ZooState])
static getAnimals(state: ZooStateModel) { ... }
```

The `ZooStateModel` annotation on `state` is not enforced by TypeScript — you could annotate it as any type and the compiler would not complain. The `ZooState` class does not carry model type information.

## Using a StateToken

A [`StateToken`](/concepts/state/token) ties the state name to its model type at the type level:

```ts
import { StateToken } from '@ngxs/store';

export const ZOO_STATE_TOKEN = new StateToken<ZooStateModel>('zoo');
```

Using the token as the `name` in `@State` and as the selector source makes the model type flow through automatically:

```ts
@State({ name: ZOO_STATE_TOKEN, defaults: { animals: [] } })
@Injectable()
export class ZooState {}

export class ZooSelectors {
  // TypeScript now enforces that `state` is ZooStateModel
  @Selector([ZOO_STATE_TOKEN])
  static getAnimals(state: ZooStateModel) {
    return state.animals;
  }
}
```

The token can also be passed directly to `select()` to select the full state model:

```ts
export class ZooComponent {
  zoo = select(ZOO_STATE_TOKEN); // Signal<ZooStateModel>
}
```

## Wrapping an Existing State Class

If migrating to `StateToken` is not immediately possible, you can wrap an existing state class in a typed `createSelector` call:

```ts
import { createSelector } from '@ngxs/store';

const zooState = createSelector([ZooState], s => s as ZooStateModel);
```

This gives downstream selectors a properly-typed input without modifying the state class:

```ts
export class ZooSelectors {
  @Selector([zooState])
  static getAnimals(state: ZooStateModel) {
    return state.animals;
  }
}
```

## Slicing State with createPropertySelectors

Rather than writing a separate `@Selector` for every property of a model, `createPropertySelectors` generates a typed selector for each property automatically:

```ts
import { createPropertySelectors } from '@ngxs/store';

export class ZooSelectors {
  static slices = createPropertySelectors<ZooStateModel>(ZOO_STATE_TOKEN);
  // slices.animals → TypedSelector<string[]>
  // slices.capacity → TypedSelector<number>
}
```

When passing a `StateToken`, no explicit type parameter is needed because the token already carries the model type. When passing a bare state class, you must supply the type manually:

```ts
static slices = createPropertySelectors<ZooStateModel>(ZooState); // type parameter required
```

The slices can be consumed directly in components:

```ts
export class ZooComponent {
  animals = select(ZooSelectors.slices.animals); // Signal<string[]>
}
```

Or composed into other selectors:

```ts
export class ZooSelectors {
  static slices = createPropertySelectors<ZooStateModel>(ZOO_STATE_TOKEN);

  @Selector([ZooSelectors.slices.animals])
  static getPandas(animals: string[]) {
    return animals.filter(a => a.includes('panda'));
  }
}
```

## Selecting a Subset with createPickSelector

`createPickSelector` takes a typed selector and an array of keys, and returns a selector that emits only when one of those picked properties changes. This is useful when a component only cares about part of a larger model:

```ts
import { createPickSelector } from '@ngxs/store';

export class ZooSelectors {
  // only re-evaluates when `animals` or `name` change — not when `capacity` changes
  static summary = createPickSelector(ZOO_STATE_TOKEN, ['animals', 'name']);
  // → TypedSelector<Pick<ZooStateModel, 'animals' | 'name'>>
}
```

`createPickSelector` requires a strongly-typed selector or `StateToken`. Passing a bare state class loses type information for the picked properties.

## Building View Models with createModelSelector

`createModelSelector` takes a map of selectors and returns a single selector whose output object has the same keys. This is the recommended way to assemble component view models from multiple states:

```ts
import { createModelSelector } from '@ngxs/store';

export class DashboardSelectors {
  static viewModel = createModelSelector({
    animals: ZooSelectors.slices.animals,
    openTime: ParkSelectors.slices.openTime,
    visitorCount: ParkSelectors.slices.visitorCount
  });
  // → TypedSelector<{ animals: string[], openTime: string, visitorCount: number }>
}
```

The output type is fully inferred from the selector map — no annotations required — provided each input selector is itself strongly typed (from a `StateToken`, `createPropertySelectors`, or an explicitly-typed `@Selector`).

```ts
export class DashboardComponent {
  vm = select(DashboardSelectors.viewModel);
}
```

```html
@if (vm(); as vm) {
<h1>Animals: {{ vm.animals.length }}</h1>
<p>Open from: {{ vm.openTime }} · Visitors: {{ vm.visitorCount }}</p>
}
```


# Selector Utils

## Why?

Selectors are one of the most powerful features in `NGXS`. When used in a correct way they are very performant due to the built-in memoization. However, in order to use selectors correctly we usually need to break down the state into smaller selectors that, in turn, will be used by other selectors. This approach is important to guarantee that selectors are only run when a change of interest has happened. The process of breaking down your state into simple selectors for each property of the state model can be tedious and usually comes with a lot of boilerplate. The objective the selector utils is to make it easy to generate these selectors, combine selectors from multiple states, and create a selector based on a subset of properties of your state.

These are the provided utils:

* [createPropertySelectors](#create-property-selectors) - create a selector for each property of an object returned by a selector.
* [createModelSelector](#create-model-selector) - create a selector that returns an object which is composed from values returned by multiple selectors.
* [createPickSelector](#create-pick-selector) - create a selector that returns a subset of an object's properties, and changes only when those properties change.

## Create Property Selectors

Let's start with a common example. Here we have a small state containing animals. Check the snippet below:

```ts
import { Injectable } from '@angular/core';
import { Selector, State } from '@ngxs/store';

export interface AnimalsStateModel {
  zebras: string[];
  pandas: string[];
  monkeys?: string[];
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: {
    zebras: [],
    pandas: [],
    monkeys: []
  }
})
@Injectable()
export class AnimalsState {}

export class AnimalsSelectors {
  @Selector([AnimalsState])
  static getZebras(state: AnimalsStateModel): string[] {
    return state.zebras;
  }

  @Selector([AnimalsState])
  static getPandas(state: AnimalsStateModel): string[] {
    return state.pandas;
  }

  @Selector([AnimalsState])
  static getMonkeys(state: AnimalsStateModel): string[] {
    return state.monkeys;
  }
}
```

Here we see how verbose the split of a state into selectors can look. We can use the `createPropertySelectors` to cleanup this code a bit. See the snippet below:

```ts
import { Selector, createPropertySelectors, select } from '@ngxs/store';

export class AnimalsSelectors {
  // creates map of selectors for each state property
  static getSlices = createPropertySelectors<AnimalStateModel>(AnimalsState);

  // slices can be used in other selectors
  @Selector([AnimalsSelectors.getSlices.zebras, AnimalsSelectors.getSlices.pandas])
  static getCountZebrasAndPandas(zebras: string[], pandas: string[]) {
    return zebras.length + pandas.length;
  }
}

@Component({
  selector: 'my-zoo',
  template: `
    <h1>Zebras</h1>
    <ol>
      @for (zebra of zebras(); track zebra) {
        <li>{{ zebra }}</li>
      }
    </ol>
  `
})
export class MyZooComponent {
  // slices can be used directly in components
  zebras = select(AnimalsSelectors.getSlices.zebras);
}
```

Here we see how the `createPropertySelectors` is used to create a map of selectors for each property of the state. The `createPropertySelectors` takes a state class and returns a map of selectors for each property of the state. The `createPropertySelectors` is very useful when we need to create a selector for each property of the state.

> **TYPE SAFETY:** Note that, in the `createPropertySelectors` call above, the model type was provided to the function as a type parameter. This was only necessary because the state class (`AnimalsSate`) was provided and the class does not include model information. The `createPropertySelectors` function will not require a type parameter if a typed selector or a `StateToken` that includes the type of the model is provided to the function.

## Create Model Selector

Sometimes we need to create a selector simply groups other selectors. For example, we might want to create a selector that maps the state to a map of pandas and zoos. We can use the `createModelSelector` to create such a selector. See the snippet below:

```ts
import { Selector, createModelSelector, select } from '@ngxs/store';

export class AnimalsSelectors {
  static getSlices = createPropertySelectors<AnimalStateModel>(AnimalsSate);

  static getPandasAndZoos = createModelSelector({
    pandas: AnimalsSelectors.getSlices.pandas,
    zoos: ZoosSelectors.getSlices.zoos
  });
}

@Component({
  selector: 'my-zoo',
  template: `
    <h1>Pandas and Zoos</h1>
    @if (pandasAndZoos(); as model) {
      <ol>
        <li>Panda Count: {{ model.pandas?.length || 0 }}</li>
        <li>Zoos Count: {{ model.zoos?.length || 0 }}</li>
      </ol>
    }
  `
})
export class MyZooComponent {
  pandasAndZoos = select(AnimalsSelectors.getPandasAndZoos);
}
```

Here we see how the `createModelSelector` is used to create a selector that maps the state to a map of pandas and zoos. The `createModelSelector` takes a map of selectors and returns a selector that maps the state to a map of the values returned by the selectors. The `createModelSelector` is very useful when we need to create a selector that groups other selectors.

> **TYPE SAFETY:** Note that it is always best to use typed selectors in the selector map provided to the `createModelSelector` function. The output model is inferred from the selector map. A state class (eg. `AnimalSate`) does not include model information and this causes issues with the type inference. It is also questionable why an entire state would be included in a model, because this breaks encapsulation and would also cause change detection to trigger more often.

## Create Pick Selector

Sometimes we need to create a selector that picks a subset of properties from the state. For example, we might want to create a selector that picks only the `zebras` and `pandas` properties from the state. We can use the `createPickSelector` to create such a selector. See the snippet below:

```ts
import { Selector, createPickSelector, select } from '@ngxs/store';

export class AnimalsSelectors {
  static getFullAnimalsState = createSelector(
    [AnimalsState],
    (state: AnimalStateModel) => state
  );

  static getZebrasAndPandas = createPickSelector(getFullAnimalsState, ['zebras', 'pandas']);
}

@Component({
  selector: 'my-zoo',
  template: `
    <h1>Zebras and Pandas</h1>
    @if (zebrasAndPandas(); as zebrasAndPandas) {
      <ol>
        <li>Zebra Count: {{ zebrasAndPandas.zebras?.length || 0 }}</li>
        <li>Panda Count: {{ zebrasAndPandas.pandas?.length || 0 }}</li>
      </ol>
    }
  `
})
export class MyZooComponent {
  zebrasAndPandas = select(AnimalsSelectors.getZebrasAndPandas);
}
```

The `zebrasAndPandas` object above would only contain the `zebras` and `pandas` properties, and not have the `monkeys` property.

Here we see how the `createPickSelector` is used to create a selector that picks a subset of properties from the state, or from any other selector that returns an object for that matter. The `createPickSelector` takes a selector which returns an object and an array of property names and returns a selector that returns a copy of the object, with only the properties that have been picked. The `createPickSelector` is very useful when we need to create a selector that picks a subset of properties from the state.

> **TYPE SAFETY:** The `createPickSelector` function should only be provided a strongly typed selector or a `StateToken` that includes the type of the model. This is so that type safety is maintained for the picked properties.

**Noteable Performance win!**

One of the most useful things about the `createPickSelector` selector (versus rolling your own that creates a trimmed object from the provided selector), is that it will only emit a new value when a picked property changes, and will not emit a new value if any of the other properties change. An Angular change detection performance enthusiasts dream!


# Error Handling

## Handling errors within selectors

```ts
@State({ ... })
class AppState {
  @Selector()
  static getCount(state: StateModel) {
    return state.count.number.value;
  }
}
```

Let's take a look at the below example:

```ts
this.store.reset({}); // reset all states
```

The catch is that when resetting the entire state, the object will no longer have those deeply nested properties (`state.count.number.value`). Given the following code:

```ts
const state = {};

function getCount() {
  return state.count.number.value;
}

const count = getCount(); // will throw
```

RxJS will automatically complete the stream under the hood if any error is thrown.

You have to disable suppressing errors using the `suppressErrors` option:

```ts
@NgModule({
  imports: [
    NgxsModule.forRoot([CountState], {
      selectorOptions: {
        suppressErrors: false
      }
    })
  ]
})
export class AppModule {}
```

This option allows to track errors and handle them.

```ts
@State({ ... })
class AppState {
  @Selector()
  static getCount(state: StateModel) {
    try {
      return state.count.number.value;
    } catch (error) {
      console.log('error', error);
      // throw error;
      // Automatic unsubscription will occur if you use the `throw` statement here. Skip it if you don't want the stream to be completed on error.
    }
  }
}
```

#### Why does RxJS unsubscribe on error?

RxJS [design guidelines](https://github.com/ReactiveX/rxjs/blob/master/docs_app/content/guide/observable.md#executing-observables) provides a great explanation of this behavior.


# Signals

NGXS offers utilities for signals that can be used with other solutions, promoting modularity and flexibility. All of these utilities are located within the `@ngxs/store` package and are independent of any specific state management framework.

## select

The initial utility is the `select` function, which retrieves a signal from the state:

```ts
import { select } from '@ngxs/store';

class AppComponent {
  invoiceId = select(InvoiceState.getInvoiceId);
}
```

It serves as a shortcut for `store.selectSignal`. eliminating the need to inject the `Store` service and invoke its `selectSignal` function.

## Create select and dispatch maps

Other utility functions include `createSelectMap` and `createDispatchMap`.

### createSelectMap

The `createSelectMap` function accepts an object where the values are selector functions:

```ts
import { createSelectMap } from '@ngxs/store';

class AppComponent {
  selectors = createSelectMap({
    invoiceId: InvoiceState.getInvoiceId,
    invoiceSignature: InvoiceState.getInvoiceSignature,
    invoiceLines: InvoiceLinesState.getInvoiceLines
  });
}
```

The `selectors` property will now be an object where the keys are the same keys you provided to the `createSelectMap`, and the values are signals from the state using the provided selectors. Consider the following template example:

```html
<div>
  <p>Invoice ID: {{ selectors.invoiceId() }}</p>
  <p>Invoice signature: {{ selectors.invoiceSignature() }}</p>
  <p>Invoice lines: {{ selectors.invoiceLines() | json }}</p>
  <!--
    Error: Property 'invoiceBody' does not exist on type { ... }
  -->
  <p>{{ selectors.invoiceBody() }}</p>
</div>
```

Properties are also `readonly` by type and functionality. Assigning to a property will result in compiler and runtime errors.

It also necessitates an injection context since it internally employs `inject`.

### createDispatchMap

The `createDispatchMap` function accepts an object where the values are action classes. It only allow action classes because they contain type information (constructor parameters):

```ts
import { createSelectMap, createDispatchMap } from '@ngxs/store';

class AppComponent {
  selectors = createSelectMap({
    invoiceId: InvoiceState.getInvoiceId,
    invoiceSignature: InvoiceState.getInvoiceSignature,
    invoiceLines: InvoiceLinesState.getInvoiceLines
  });

  actions = createDispatchMap({
    updateInvoiceSignature: InvoiceActions.UpdateInvoiceSignature,
    reloadInvoiceLines: InvoiceLinesActions.ReloadInvoiceLines
  });
}
```

The `actions` property will now be an object where the keys are the same keys, and the values are functions that accept the same arguments as action constructors and return observables (representing the dispatch result):

```html
<button (click)="actions.reloadInvoiceLines(selectors.invoiceId())">
  Reload invoice lines
</button>
```

### Using utilities with NgRx SignalStore

These utility functions can be easily integrated for use with the NgRx SignalStore solution. We will need to create simple [store features](https://ngrx.io/guide/signals/signal-store/custom-store-features) and include them in our codebase:

```ts
import { signalStoreFeature, withComputed } from '@ngrx/signals';
import { createSelectMap, SelectorMap, createDispatchMap, ActionMap } from '@ngxs/store';

export function withSelectors<T extends SelectorMap>(selectorMap: T) {
  return signalStoreFeature(withComputed(() => createSelectMap(selectorMap)));
}

export function withActions<T extends ActionMap>(actionMap: T) {
  return signalStoreFeature(withMethods(() => createDispatchMap(actionMap)));
}
```

Now, let's explore how these utilities can assist in creating a signal store by using these straightforward signal store features:

```ts
import { signalStore } from '@ngrx/signals';

import { withSelectors, withActions } from './utilities-we-created';

export const InvoicesStore = signalStore(
  withSelectors({
    invoices: InvoicesState.getInvoice,
    signatures: InvoicesState.getSignatures,
    totalAmountDue: InvoicesState.getTotalAmountDue
  }),

  withActions({
    getInvoice: InvoicesActions.getInvoices,
    updateTotalAmountDue: InvoicesActions.UpdateTotalAmountDue
  })
);
```

The reason we didn't tie our solution to NgRx signals is because we aimed for it to be solution-agnostic. Therefore, these utility functions, `createSelectMap` and `createDispatchMap`, can be utilized in a similar manner with other state management solutions.


# Select Decorator

{% hint style="danger" %}
**DEPRECATED**

[Find out why we are deprecating the select decorator](/deprecations/select-decorator-deprecation)
{% endhint %}

You can select slices of data from the store using the `@Select` decorator. It has a few different ways to get your data out, whether passing the state class, a function, a different state class or a memoized selector.

```ts
import { Select } from '@ngxs/store';
import { ZooState, ZooStateModel } from './zoo.state';

@Component({ ... })
export class ZooComponent {
  // Reads the name of the state from the state class
  @Select(ZooState) animals$: Observable<string[]>;

  // Uses the pandas memoized selector to only return pandas
  @Select(ZooState.pandas) pandas$: Observable<string[]>;

  // Also accepts a function like our select method
  @Select(state => state.zoo.animals) animals$: Observable<string[]>;

  // Reads the name of the state from the parameter
  @Select() zoo$: Observable<ZooStateModel>;
}
```


# STYLE GUIDE

Below are suggestions for naming and style conventions.

### State Suffix

A state should always be suffixed with the word `State`. Prefer: `ZooState` Avoid: `Zoo`

### State Filenames

States should have a `.state.ts` suffix for the filename

### State Interfaces

State interfaces should be named the name of the state followed by the `Model` suffix. If my state were called `ZooState`, we would call my state interface `ZooStateModel`.

### Select Suffix

Selects returning an observable should be suffixed with `$`. Prefer: `animals$`. Selects returning a signal should not have a suffix. Prefer: `animals`.

### Plugin Suffix

Plugins should end with the `Plugin` suffix

### Plugin Filenames

Plugins file names should end with `.plugin.ts`

### Folder Organization

Global states should be organized under `src/shared/state`. Feature states should live within the respective feature folder structure `src/app/my-feature`. Actions can live within the state file but are recommended to be a separate file like: `zoo.actions.ts`

### Action Suffixes

Actions should NOT have a suffix

### Unit Tests

Unit tests for the state should be named `my-state-name.state.spec.ts`

### Action Operations

Actions should NOT deal with view related operations (i.e. showing popups/etc). Use the action stream to handle these types of operations

### Avoid Saving Class Based Instances in Your State

The objects stored in your state should be immutable and should support serialization and deserialization. It is therefore recommended to store pure object literals in your state. Class based instances are not trivial to serialize and deserialize, and also are generally focused on encapsulating internals and mutating internal state through exposed operations. This does not match the requirement for the data stored in state.

This also applies to the usage of data collections such as Set, Map, WeakMap, WeakSet, etc. Since they are not amenable to deserialization and cannot easily be presented for normalization.

#### Avoid

```ts
export class Todo {
  constructor(
    readonly title: string,
    readonly isCompleted = false
  ) {}
}

@State<Todo[]>({
  name: 'todos',
  defaults: []
})
@Injectable()
class TodosState {
  @Selector()
  static getTodos(state: Todo[]) {
    return state;
  }

  @Action(AddTodo)
  add(ctx: StateContext<Todo[]>, action: AddTodo): void {
    // Avoid new Todo(title)
    ctx.setState((state: Todo[]) => state.concat(new Todo(action.title)));
  }
}

@Component({
  selector: 'app',
  template: `
    @for (todo of todos(); track todo) {
      {{ todo.isCompleted }}
    }
  `
})
class AppComponent {
  todos = inject(Store).selectSignal(TodosState.getTodos);
}
```

It is not recommended to add Class based object instances to your state because this can lead to undefined behavior in the future.

#### Prefer

```ts
export interface TodoModel {
  title: string;
  isCompleted: boolean;
}

@State<TodoModel[]>({
  name: 'todos',
  defaults: []
})
@Injectable()
class TodosState {
  @Selector()
  static getTodos(state: Todo[]) {
    return state;
  }

  @Action(AddTodo)
  add(ctx: StateContext<TodoModel[]>, action: AddTodo): void {
    ctx.setState((state: TodoModel[]) =>
      state.concat({ title: action.title, isCompleted: false })
    );
  }
}

@Component({
  selector: 'app',
  template: `
    @for (todo of todos(); track todo) {
      {{ todo.isCompleted }}
    }
  `
})
class AppComponent {
  todos = inject(Store).selectSignal(TodosState.getTodos);
}
```

### Flatten Deep Object Graphs

The general recommendation for handling hierarchical data in Redux is to normalise it. This would entail flattening it in the same way that you would design relational tables, having keys for references to parent objects.

#### Avoid

```ts
export interface RowStateModel {
  id: number;
}

export interface GridStateModel {
  id: number;
  rows: Map<number, RowState>;
}

export interface GridCollectionStateModel {
  grids: Map<number, GridState>;
}

@State<RowStateModel>({
  name: 'row',
  defaults: {
    id: -1
  }
})
@Injectable()
export class RowState {}

@State<GridStateModel>({
  name: 'grid',
  defaults: {
    id: -1,
    rows: new Map<number, RowState>()
  }
})
@Injectable()
export class GridState {}

@State<GridCollectionStateModel>({
  name: 'grid-collection',
  defaults: {
    grids: new Map<number, GridState>()
  }
})
@Injectable()
export class GridCollectionState {}
```

Note: It is not recommended to use data collections such as Set, Map, WeakMap, WeakSet, etc. Since they are not amenable to deserialization and cannot easily be presented for normalization.

#### Prefer

```ts
export interface RowStateModel {
  id: number;
}

export interface GridStateModel {
  id: number;
  rows: {
    [id: number]: RowStateModel;
  };
}

export interface GridCollectionStateModel {
  grids: {
    [id: number]: GridStateModel;
  };
}

@State<RowStateModel>({
  name: 'row',
  defaults: {
    id: -1
  }
})
@Injectable()
export class RowState {}

@State<GridStateModel>({
  name: 'grid',
  defaults: {
    id: -1,
    rows: {}
  }
})
@Injectable()
export class GridState {}

@State<GridCollectionStateModel>({
  name: 'grid-collection',
  defaults: {
    grids: {}
  }
})
@Injectable()
export class GridCollectionState {}
```


# PLUGINS

Next, let's talk about plugins. Similar to Redux's meta reducers, we have a plugin interface that allows you to build a global plugin for your state.

All you have to do is call `withNgxsPlugin` with a plugin class. If your plugins have options associated with them, we also suggest defining an injection token.

Let's take a look at a basic example of a logger:

```ts
import { makeEnvironmentProviders, InjectionToken, Injectable, Inject } from '@angular/core';
import { withNgxsPlugin } from '@ngxs/store';
import { NgxsPlugin, NgxsNextPluginFn } from '@ngxs/store/plugins';

export const NGXS_LOGGER_PLUGIN_OPTIONS = new InjectionToken('NGXS_LOGGER_PLUGIN_OPTIONS');

@Injectable()
export class LoggerPlugin implements NgxsPlugin {
  constructor(@Inject(NGXS_LOGGER_PLUGIN_OPTIONS) private options: any) {}

  handle(state: any, action: any, next: NgxsNextPluginFn) {
    console.log('Action started!', state);
    return next(state, action).pipe(
      tap(result => {
        console.log('Action happened!', result);
      })
    );
  }
}

export function withNgxsLoggerPlugin(options?: any) {
  return makeEnvironmentProviders([
    withNgxsPlugin(LoggerPlugin),
    {
      provide: NGXS_LOGGER_PLUGIN_OPTIONS,
      useValue: options
    }
  ]);
}
```

You can also use pure functions for plugins. The above example in a pure function would look like this:

```ts
import { NgxsNextPluginFn } from '@ngxs/store/plugins';

export function logPlugin(state: any, action: any, next: NgxsNextPluginFn) {
  // Note that plugin functions are called within an injection context,
  // allowing you to inject dependencies.
  const options = inject(NGXS_LOGGER_PLUGIN_OPTIONS);

  console.log('Action started!', state);
  return next(state, action).pipe(tap(result) => {
    console.log('Action happened!', result);
  });
}
```

To register a plugin with NGXS, add the plugin to your `provideStore` as an NGXS feature and optionally pass in the plugin options like this:

```ts
export const appConfig: ApplicationConfig = {
  providers: [provideStore([ZooState], withNgxsLoggerPlugin({}))]
};
```

## Dynamic Plugin Registration

Use `registerNgxsPlugin` to register a plugin at runtime from within an injection context (e.g., a component constructor or `runInInjectionContext`). The plugin is automatically torn down when the injection context is destroyed.

```ts
import { Component } from '@angular/core';
import { registerNgxsPlugin } from '@ngxs/store';
import { MyPlugin } from './my.plugin';

@Component({
  selector: 'app-root',
  template: '...'
})
export class AppComponent {
  constructor() {
    registerNgxsPlugin(MyPlugin);
  }
}
```

Plugin functions are also supported:

```ts
import { registerNgxsPlugin } from '@ngxs/store';
import { myPluginFn } from './my.plugin';

@Component({ selector: 'app-root', template: '...' })
export class AppComponent {
  constructor() {
    registerNgxsPlugin(myPluginFn);
  }
}
```

To register outside of a class constructor, use Angular's `runInInjectionContext`:

```ts
import { Injector, runInInjectionContext } from '@angular/core';
import { registerNgxsPlugin } from '@ngxs/store';
import { MyPlugin } from './my.plugin';

// injector obtained from inject(Injector) or ApplicationRef
runInInjectionContext(injector, () => registerNgxsPlugin(MyPlugin));
```

> **Note:** `registerNgxsPlugin` must be called within an [injection context](https://angular.dev/guide/di/dependency-injection-context). In development mode, registering the same plugin twice will throw an error to prevent unexpected behavior.


# CLI

![CLI Screenshot](/files/-LqoSUl2yJqhxFS2cBEb)

## Install

The CLI can be installed using NPM:

```bash
npm install @ngxs/cli -g

# or if you use yarn
yarn global add @ngxs/cli
```

## Usage

```bash
ngxs
```

## Options (silent)

```bash
  ▓█▓▒▒▒▒▒▒▒▒▒▒██░   ▓█▒░░░░░░░░░░░░░  ░▒▒▒▒▒██░ ░██▒▒▒▒▒░  ░██▓▒▒▒▒▒▒▒▒▒▒▒▒░
 ░█░░██████████░░█  ░█░▒█████████████  ░█████░▒█ █▓░█████▒  ██ █████████████▓
 ░█ ▓█        █░░█  ░█ ▓▓                  ░█░▒█ █▓░█░      ██ █░
 ░█ ▓█        █░░█  ░█ ▓▓                  ░█░▒█░█▓░█░      ██ █░
 ░█ ▓█        █░░█  ░█ ▓▓   ░▓▓▓▓▓▓██      ░█░░▓▓▓░░█░      ▓█ ░▓▓▓▓▓▓▓▓▓███
 ░█ ▓█        █░░█  ░█ ▓▓   ░█████░░█      ░█░░███▒░█░       ▒████████████ █▒
 ░█ ▓█        █░░█  ░█ ▓▓       ░█░░█      ░█░▒█ █▓░█░                  ▓█ █▓
 ░█ ▓█        █░░█  ░█ ▓▓       ░█░░█      ░█░▒█ █▓░█░                  ▓█ █▓
 ░█ ▓█        █░░█  ░█░░█████████▓ ░█  ░████▓ ▓█ ██ ▓████▒  █████████████▒░█▒
 ░█ ▓█        █░░█   ░███████████████  ░██████▓   ▒██████▒  ███████████████░



NGXS CLI

  $ ngxs --name name --spec boolean --directory path --folder-name name
  $ ngxs --help

Options

  --name name         Store name
  --directory path    By default, the prompt is set to the current directory
  --folder-name name   Use your own folder name, default: state
  --spec boolean      Creates a spec file for store, default: true

Custom template generator

  --plopfile path   Path to the plopfile
```

#### What is Plop?

[Plop](https://www.npmjs.com/package/plop) is what I like to call a "micro-generator framework." Now, I call it that because it is a small tool that gives you a simple way to generate code or any other type of flat text files in a consistent way. You see, we all create structures and patterns in our code (routes, controllers, components, helpers, etc). These patterns change and improve over time so when you need to create a NEW insert-name-of-pattern-here, it's not always easy to locate the files in your codebase that represent the current "best practice." That's where plop saves you. With plop, you have your "best practice" method of creating any given pattern in CODE. Code that can easily be run from the terminal by typing plop. Not only does this save you from hunting around in your codebase for the right files to copy, but it also turns "the right way" into "the easiest way" to make new files.


# Logger

A simple console log plugin to log actions as they are processed.

## Installation

```bash
npm i @ngxs/logger-plugin

# or if you are using yarn
yarn add @ngxs/logger-plugin

# or if you are using pnpm
pnpm i @ngxs/logger-plugin
```

## Usage

When calling `provideStore`, include `withNgxsLoggerPlugin` in your app config:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsLoggerPlugin } from '@ngxs/logger-plugin';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], withNgxsLoggerPlugin())]
};
```

If you are still using modules, include the `NgxsLoggerPluginModule` plugin in your root app module:

```ts
import { NgxsModule } from '@ngxs/store';
import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin';

@NgModule({
  imports: [NgxsModule.forRoot([]), NgxsLoggerPluginModule.forRoot()]
})
export class AppModule {}
```

### Options

The plugin supports the following options passed via the `forRoot` method:

* `logger`: Supply a different logger, useful for logging to backend. Defaults to `console`.
* `collapsed`: Collapse the log by default or not. Defaults to `true`.
* `disabled`: Disable the logger during production. Defaults to `false`.
* `filter`: Filter actions to be logged. Takes action and state snapshot as parameters. Default predicate returns `true` for all actions.

```ts
import { provideStore, getActionTypeFromInstance } from '@ngxs/store';
import { withNgxsLoggerPlugin } from '@ngxs/logger-plugin';

import { environment } from '../environments/environment';
import { customLogger } from './path/to/custom/logger';
import { SomeAction } from './path/to/some/action';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsLoggerPlugin({
        // Use customLogger instead of console
        logger: customLogger,
        // Do not collapse log groups
        collapsed: false,
        // Do not log in production mode
        disabled: environment.production,
        // Do not log SomeAction
        filter: action => getActionTypeFromInstance(action) !== SomeAction.type
      })
    )
  ]
};
```

Or with the module approach:

```ts
import { NgxsModule, getActionTypeFromInstance } from '@ngxs/store';
import { NgxsLoggerPluginModule } from '@ngxs/logger-plugin';

import { environment } from '../environments/environment';
import { customLogger } from './path/to/custom/logger';
import { SomeAction } from './path/to/some/action';

@NgModule({
  imports: [
    NgxsModule.forRoot([]),
    NgxsLoggerPluginModule.forRoot({
      // Use customLogger instead of console
      logger: customLogger,
      // Do not collapse log groups
      collapsed: false,
      // Do not log in production mode
      disabled: environment.production,
      // Do not log SomeAction
      filter: action => getActionTypeFromInstance(action) !== SomeAction.type
    })
  ]
})
export class AppModule {}
```

> The `filter` predicate takes state snapshot as the second parameter. This should prove useful for some edge cases. However, beware of the fact that the predicate is called for every action dispatched. You may consider using a memoized function for filters more complicated than a simple action comparison.

### Notes

You should always include the logger as the last plugin in your configuration. For instance, if you were to include logger before a plugin like the storage plugin, the initial state would not be reflected.


# Devtools

Reference: [Redux Devtools](https://github.com/reduxjs/redux-devtools/tree/master/extension)

Plugin with integration:

* [Chrome - Redux Devtools](https://chrome.google.com/webstore/detail/redux-devtools/lmhkpmbekcpmknklioeibfkpmmfibljd)
* [Firefox - Redux Devtools](https://addons.mozilla.org/en-US/firefox/addon/reduxdevtools/)

![Devtools Screenshot](/files/-LZoLfd2chVZNxmDsZIv)

## Installation

```bash
npm i @ngxs/devtools-plugin

# or if you are using yarn
yarn add @ngxs/devtools-plugin

# or if you are using pnpm
pnpm i @ngxs/devtools-plugin
```

## Usage

When calling `provideStore`, include `withNgxsReduxDevtoolsPlugin` in your app config:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsReduxDevtoolsPlugin } from '@ngxs/devtools-plugin';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], withNgxsReduxDevtoolsPlugin())]
};
```

If you are still using modules, include the `NgxsReduxDevtoolsPluginModule` plugin in your root app module:

```ts
import { NgxsModule } from '@ngxs/store';
import { NgxsReduxDevtoolsPluginModule } from '@ngxs/devtools-plugin';

@NgModule({
  imports: [NgxsModule.forRoot([]), NgxsReduxDevtoolsPluginModule.forRoot()]
})
export class AppModule {}
```

### Options

The plugin supports the following options passed via the `forRoot` method:

* `name`: Set the name by which this store instance is referenced in devtools (Default: 'NGXS')
* `disabled`: Disable the devtools during production
* `maxAge`: Max number of entries to keep.
* `latency`: If more than one action is dispatched in the indicated interval, all new actions will be collected and sent at once. It is the joint between performance and speed. When set to 0, all actions will be sent instantly. Set it to a higher value when experiencing perf issues (also maxAge to a lower value). Default is 500 ms.
* `actionsBlacklist`: string or array of strings as regex - actions types to be hidden in the monitors (while passed to the reducers). If actionsWhitelist specified, actionsBlacklist is ignored.
* `actionsWhitelist`: string or array of strings as regex - actions types to be shown in the monitors (while passed to the reducers). If actionsWhitelist specified, actionsBlacklist is ignored.
* `predicate`: called for every action before sending, takes state and action object, and returns true in case it allows sending the current data to the monitor. Use it as a more advanced version of actionsBlacklist/actionsWhitelist parameters
* `actionSanitizer`: Reformat actions before sending to dev tools
* `stateSanitizer`: Reformat state before sending to devtools
* `trace`: if set to `true`, will include stack trace for every dispatched action, so you can see it in trace tab jumping directly to that part of code
* `traceLimit`: maximum stack trace frames to be stored (in case trace option was provided as true)

### Notes

You should always include the devtools as the last plugin in your configuration. For instance, if you were to include devtools before a plugin like the storage plugin, the initial state would not be reflected.


# Storage

Back your stores with `localStorage`, `sessionStorage` or any other mechanism you wish.

## Installation

```bash
npm i @ngxs/storage-plugin

# or if you are using yarn
yarn add @ngxs/storage-plugin

# or if you are using pnpm
pnpm i @ngxs/storage-plugin
```

## Usage

When calling `provideStore`, include `withNgxsStoragePlugin` in your app config:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsStoragePlugin } from '@ngxs/storage-plugin';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsStoragePlugin({
        keys: '*'
      })
    )
  ]
};
```

If you are still using modules, include the `NgxsStoragePluginModule` plugin in your root app module:

```ts
import { NgxsModule } from '@ngxs/store';
import { NgxsStoragePluginModule } from '@ngxs/storage-plugin';

@NgModule({
  imports: [NgxsModule.forRoot([]), NgxsStoragePluginModule.forRoot({ keys: '*' })]
})
export class AppModule {}
```

It is recommended to register the storage plugin before other plugins so initial state can be picked up by those plugins.

### Options

The plugin has the following optional values:

* `keys`: State name(s) to be persisted. You can pass an array of strings that can be deeply nested via dot notation. If not provided, you must explicitly specify the `*` option.
* `namespace`: The namespace is used to prefix the key for the state slice. This is necessary when running micro frontend applications which use storage plugin. The namespace will eliminate the conflict between keys that might overlap.
* `storage`: Storage strategy to use. This defaults to LocalStorage but you can pass SessionStorage or anything that implements the StorageEngine API.
* `deserialize`: Custom deserializer. Defaults to `JSON.parse`
* `serialize`: Custom serializer. Defaults to `JSON.stringify`
* `migrations`: Migration strategies
* `beforeSerialize`: Interceptor executed before serialization
* `afterDeserialize`: Interceptor executed after deserialization

### Keys option

The `keys` option is used to determine what states should be persisted in the storage. `keys` shouldn't be a random string, it has to coincide with your state names. Let's look at the below example:

```ts
// novels.state.ts
@State<Novel[]>({
  name: 'novels',
  defaults: []
})
@Injectable()
export class NovelsState {}

// detectives.state.ts
@State<Detective[]>({
  name: 'detectives',
  defaults: []
})
@Injectable()
export class DetectivesState {}
```

In order to persist all states, you have to provide `*` as the `keys` option:

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: '*'
      })
    )
  ]
};
```

But what if we wanted to persist only `NovelsState`? Then we would have needed to pass its name to the `keys` option:

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: ['novels']
      })
    )
  ]
};
```

It's also possible to provide a state class as opposed to its name:

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: [NovelsState]
      })
    )
  ]
};
```

And if we wanted to persist `NovelsState` and `DetectivesState`:

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: ['novels', 'detectives']
      })
    )
  ]
};
```

Or using state classes:

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: [NovelsState, DetectivesState]
      })
    )
  ]
};
```

You can even combine state classes and strings:

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: ['novels', DetectivesState]
      })
    )
  ]
};
```

This is very useful for avoiding the persistence of runtime-only states that should not be saved to any storage.

It is also possible to provide storage engines for individual keys. For example, if we want to persist `NovelsState` in the local storage and `DetectivesState` in the session storage, the signature for the key will appear as follows:

```ts
import {
  withNgxsStoragePlugin,
  LOCAL_STORAGE_ENGINE,
  SESSION_STORAGE_ENGINE
} from '@ngxs/storage-plugin';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: [
          {
            key: 'novels', // or `NovelsState`
            engine: LOCAL_STORAGE_ENGINE
          },
          {
            key: DetectivesState, // or `detectives`
            engine: SESSION_STORAGE_ENGINE
          }
        ]
      })
    )
  ]
};
```

`LOCAL_STORAGE_ENGINE` and `SESSION_STORAGE_ENGINE` are injection tokens that resolve to `localStorage` and `sessionStorage`, respectively. These tokens should not be used in apps with server-side rendering as it will throw an exception stating that these symbols are not defined in the global scope. Instead, it is recommended to provide a custom storage engine. The `engine` property can also refer to classes that implement the `StorageEngine` interface:

```ts
import { withNgxsStoragePlugin, StorageEngine } from '@ngxs/storage-plugin';

@Injectable({ providedIn: 'root' })
export class MyCustomStorageEngine implements StorageEngine {
  // ...
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: [
          {
            key: 'novels',
            engine: MyCustomStorageEngine
          }
        ]
      })
    )
  ]
};
```

The `engine` property also accepts a factory function `() => StorageEngine`. The function runs in an Angular injection context, so `inject()` is available inside it. This is useful when the same engine class needs different construction arguments for different keys:

```ts
import { inject } from '@angular/core';
import { withNgxsStoragePlugin, StorageEngine } from '@ngxs/storage-plugin';

export class MyCustomStorageEngine implements StorageEngine {
  constructor(private readonly fallback: StorageEngine | null) {}
  // ...
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [NovelsState, DetectivesState],
      withNgxsStoragePlugin({
        keys: [
          {
            key: 'novels',
            engine: () => new MyCustomStorageEngine(inject(SESSION_STORAGE_ENGINE))
          },
          {
            key: 'detectives',
            engine: () => new MyCustomStorageEngine(null) // no fallback storage
          }
        ]
      })
    )
  ]
};
```

### Namespace Option

The namespace option should be provided when the storage plugin is used in micro frontend applications. The namespace may equal the app name and will prefix keys for state slices:

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsStoragePlugin({
        keys: '*',
        namespace: 'auth'
      })
    )
  ]
};
```

### Custom Storage Engine

You can add your own storage engine by implementing the `StorageEngine` interface:

```ts
import { withNgxsStoragePlugin, StorageEngine, STORAGE_ENGINE } from '@ngxs/storage-plugin';

@Injectable()
export class MyStorageEngine implements StorageEngine {
  getItem(key: string): any {
    // Your logic here
  }

  setItem(key: string, value: any): void {
    // Your logic here
  }
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsStoragePlugin({
        keys: '*'
      })
    ),

    {
      provide: STORAGE_ENGINE,
      useClass: MyStorageEngine
    }
  ]
};
```

### Serialization Interceptors

You can define your own logic before or after the state gets serialized or deserialized.

* `beforeSerialize`: Use this option to alter the state before it gets serialized.
* `afterSerialize`: Use this option to alter the state after it gets deserialized. For instance, you can use it to instantiate a concrete class.

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [CounterState],
      withNgxsStoragePlugin({
        keys: ['counter'],
        beforeSerialize: (obj, key) => {
          if (key === 'counter') {
            return {
              count: obj.count < 10 ? obj.count : 10
            };
          }
          return obj;
        },
        afterDeserialize: (obj, key) => {
          if (key === 'counter') {
            return new CounterInfoStateModel(obj.count);
          }
          return obj;
        }
      })
    )
  ]
};
```

### Migrations

You can migrate data from one version to another during the startup of the store. Below is a strategy to migrate my state from `animals` to `newAnimals`.

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsStoragePlugin({
        keys: '*',
        migrations: [
          {
            version: 1,
            key: 'zoo',
            versionKey: 'myVersion',
            migrate: state => {
              return {
                newAnimals: state.animals,
                version: 2 // Important to set this to the next version!
              };
            }
          }
        ]
      })
    )
  ]
};
```

In the migration strategy, we define:

* `version`: The version we are migrating
* `versionKey`: The identifier for the version key (Defaults to 'version')
* `migrate`: A function that accepts a state and expects the new state in return.
* `key`: The key for the item to migrate. If not specified, it takes the entire storage state.

Note: It's important to specify the strategies in the order of which they should progress.

### Feature States

We can also add states at the feature level when invoking `provideStates`, such as within `Route` providers. This is useful when we want to avoid the root level, responsible for providing the store, from being aware of any feature states. If we do not specify any states to be persisted at the root level, we should specify an empty list:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsStoragePlugin } from '@ngxs/storage-plugin';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], withNgxsStoragePlugin({ keys: [] }))]
};
```

If `keys` is an empty list, it indicates that the plugin should not persist any state until it's explicitly added at the feature level.

After registering the `AnimalsState` at the feature level, we also want to persist this state in storage:

```ts
import { provideStates } from '@ngxs/store';
import { withStorageFeature } from '@ngxs/storage-plugin';

export const routes: Routes = [
  {
    path: 'animals',
    loadComponent: () => import('./animals'),
    providers: [provideStates([AnimalsState], withStorageFeature([AnimalsState]))]
  }
];
```

Please note that at the root level, `keys` should not be set to `*` because `*` indicates persisting everything.


# Forms

Often when building Reactive Forms in Angular, you need to bind values from the store to the form and vice versa. The values from the store are observable and the reactive form accepts raw objects, as a result we end up monkey patching this back and forth.

In addition to these issues, there are workflows where you want to fill out a form and leave and then come back and resume your current status. This is an excellent use case for stores and we can conquer that case with this plugin.

In a nutshell, this plugin helps to keep your forms and state in sync.

## Installation

```bash
npm i @ngxs/form-plugin

# or if you are using yarn
yarn add @ngxs/form-plugin

# or if you are using pnpm
pnpm i @ngxs/form-plugin
```

## Usage

When calling `provideStore`, include `withNgxsFormPlugin` in your app config:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsFormPlugin } from '@ngxs/form-plugin';

import { NovelsState } from './novels.state';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([NovelsState], withNgxsFormPlugin())]
};
```

If you are still using modules, include the `NgxsFormPluginModule` plugin in your root app module:

```ts
import { NgxsFormPluginModule } from '@ngxs/form-plugin';

import { NovelsState } from './novels.state';

@NgModule({
  imports: [NgxsModule.forRoot([NovelsState]), NgxsFormPluginModule.forRoot()]
})
export class AppModule {}
```

If your form is used in a standalone component, it must be imported there as well:

```ts
import { NgxsFormDirective } from '@ngxs/form-plugin';

@Component({
  ...,
  standalone: true,
  imports: [ReactiveFormsModule, NgxsFormDirective]
})
export class AppComponent {}
```

### Form State

Define your default form state as part of your application state.

```ts
import { Injectable } from '@angular/core';
import { State } from '@ngxs/store';

@State({
  name: 'novels',
  defaults: {
    newNovelForm: {
      model: undefined,
      dirty: false,
      status: '',
      errors: {}
    }
  }
})
@Injectable()
export class NovelsState {}
```

### Form Setup

In your component, you would implement the reactive form and decorate the form with the `ngxsForm` directive with the path of your state object. We are passing the *string* path to `ngxsForm`. The directive uses this path to connect itself to the store and setup bindings.

```ts
import { Component } from '@angular/core';
import { FormGroup, FormControl } from '@angular/forms';
import { NgxsFormDirective } from '@ngxs/form-plugin';

@Component({
  selector: 'new-novel-form',
  template: `
    <form [formGroup]="newNovelForm" ngxsForm="novels.newNovelForm" (ngSubmit)="onSubmit()">
      <input type="text" formControlName="novelName" />
      <button type="submit">Create</button>
    </form>
  `,
  standalone: true,
  imports: [ReactiveFormsModule, NgxsFormDirective]
})
export class NewNovelComponent {
  newNovelForm = new FormGroup({
    novelName: new FormControl()
  });

  onSubmit() {
    //
  }
}
```

Now anytime your form updates, your state will also reflect the new state.

The directive also has two inputs you can utilize as well:

* `ngxsFormDebounce: number | string` - Debounce the value changes from the form. Default value: `100`. Ignored if:
  * the provided value is less than `0` (for instance, `ngxsFormDebounce="-1"` is valid)
  * `updateOn` is `blur` or `submit`
* `ngxsFormClearOnDestroy: boolean` - Clear the state on destroy of the form.

### Actions

In addition to it automatically keeping track of the form, you can also manually dispatch actions for things like resetting the form state. For example:

```ts
this.store.dispatch(
  new UpdateFormDirty({
    dirty: false,
    path: 'novels.newNovelForm'
  })
);
```

The form plugin comes with the following `actions` out of the box:

* `UpdateFormStatus({ status, path })` - Update the form status
* `UpdateFormValue({ value, path, propertyPath? })` - Update the form value (or optionally an inner property value)
* `UpdateFormDirty({ dirty, path })` - Update the form dirty status
* `SetFormDisabled(path)` - Set the form to disabled
* `SetFormEnabled(path)` - Set the form to enabled
* `SetFormDirty(path)` - Set the form to dirty (shortcut for `UpdateFormDirty`)
* `SetFormPristine(path)` - Set the form to pristine (shortcut for `UpdateFormDirty`)
* `ResetForm({ path, value? })` - Reset the form with or without the form value.

### Updating Specific Form Properties

The form plugin exposes the `UpdateFormValue` action that provides the ability to update nested form properties by supplying a `propertyPath` parameter.

```ts
interface NovelsStateModel {
  newNovelForm: {
    model?: {
      novelName: string;
      authors: {
        name: string;
      }[];
    };
  };
}

@State<NovelsStateModel>({
  name: 'novels',
  defaults: {
    newNovelForm: {
      model: undefined
    }
  }
})
@Injectable()
export class NovelsState {}
```

The state contains information about the new novel name and its authors. Let's create a component that will render the reactive form with bounded `ngxsForm` directive:

```ts
import { Component } from '@angular/core';
import { FormBuilder } from '@angular/forms';
import { NgxsFormDirective } from '@ngxs/form-plugin';

@Component({
  selector: 'new-novel-form',
  template: `
    <form [formGroup]="newNovelForm" ngxsForm="novels.newNovelForm" (ngSubmit)="onSubmit()">
      <input type="text" formControlName="novelName" />

      @for (author of newNovelForm.get('authors').value; let index = $index; track author) {
        <div formArrayName="authors">
          <div [formGroupName]="index">
            <input formControlName="name" />
          </div>
        </div>
      }

      <button type="submit">Create</button>
    </form>
  `,
  standalone: true,
  imports: [ReactiveFormsModule, NgxsFormDirective]
})
export class NewNovelComponent {
  newNovelForm = this.fb.group({
    novelName: 'Zenith',
    authors: this.fb.array([
      this.fb.group({
        name: 'Sasha Alsberg'
      })
    ])
  });

  constructor(private fb: FormBuilder) {}

  onSubmit() {
    //
  }
}
```

Let's look at the component above again. Assume we want to update the name of the first author in our form, from anywhere in our application. The code would look as follows:

```ts
store.dispatch(
  new UpdateFormValue({
    path: 'novels.newNovelForm',
    value: {
      name: 'Lindsay Cummings'
    },
    propertyPath: 'authors.0'
  })
);
```

### Debouncing

The `ngxsFormDebounce` is used alongside `debounceTime` and pipes form's `valueChanges` and `statusChanges`. This implies that state updates are asynchronous by default. Suppose you dispatch the `UpdateFormValue`, which should patch the form value. In that case, you won't get the updated state immediately because the `debounceTime` is set to `100` by default. Given the following example:

```ts
interface NovelsStateModel {
  newNovelForm: {
    model?: {
      novelName: string;
      paperBound: boolean;
    };
  };
}

export class NovelsState {
  @Action(SubmitNovelsForm)
  submitNovelsForm(ctx: StateContext<NovelsStateModel>) {
    console.log(ctx.getState().newNovelForm.model);

    ctx.dispatch(
      new UpdateFormValue({
        value: { paperBound: true },
        path: 'novels.newNovelForm'
      })
    );

    console.log(ctx.getState().newNovelForm.model);
  }
}
```

You may expect to see `{ paperBound: true, novelName: null }` being logged. Still, the second `console.log` will log `{ paperBound: true }`, pretending the `novelName` value is lost. You'll see the final update state if you wrap the second `console.log` into a `setTimeout`:

```ts
ctx.dispatch(
  new UpdateFormValue({
    value: { paperBound: true },
    path: 'novels.newNovelForm'
  })
);

setTimeout(() => {
  console.log(ctx.getState().newNovelForm.model);
}, 100);
```

If you need to get state updates synchronously, you may want to set the `ngxsFormDebounce` to `-1`; this won't pipe value changes with `debounceTime`.


# Web Socket

Bind server web socket events to Ngxs store actions.

## Installation

```bash
npm i @ngxs/websocket-plugin

# or if you are using yarn
yarn add @ngxs/websocket-plugin

# or if you are using pnpm
pnpm i @ngxs/websocket-plugin
```

## Configuration

When calling `provideStore`, include `withNgxsWebSocketPlugin` in your app config:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsWebSocketPlugin } from '@ngxs/websocket-plugin';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsWebSocketPlugin({
        url: 'ws://localhost:4200'
      })
    )
  ]
};
```

If you are still using modules, include the `NgxsWebSocketPluginModule` plugin in your root app module:

```ts
import { NgxsModule } from '@ngxs/store';
import { NgxsWebSocketPluginModule } from '@ngxs/websocket-plugin';

@NgModule({
  imports: [
    NgxsModule.forRoot([]),
    NgxsWebSocketPluginModule.forRoot({
      url: 'ws://localhost:4200'
    })
  ]
})
export class AppModule {}
```

The plugin has a variety of options that can be passed:

* `url`: Url of the web socket connection. Can be passed here or by the `ConnectWebSocket` action.
* `typeKey`: Object property that maps the web socket message to a action type. Default: `type`
* `serializer`: Serializer used before sending objects to the web socket. Default: `JSON.stringify`
* `deserializer`: Deserializer used for messages arriving from the web socket. Default: `JSON.parse`

## Usage

Once connected, any message that comes across the web socket will be bound to the state event stream.

Let's assume that a server side web socket sends a message to the client in the following format:

```json
{
  "type": "[Chat] Add message",
  "from": "Artur",
  "message": "Hello NGXS"
}
```

We will want to make an action that corresponds to this web socket message, that will look like:

```ts
export class AddMessage {
  static readonly type = '[Chat] Add message';

  constructor(
    readonly from: string,
    readonly message: string
  ) {}
}
```

Assume we've got some `messages` state where we store our chat messages:

```ts
export interface Message {
  from: string;
  message: string;
}

@State<Message[]>({
  name: 'messages',
  defaults: []
})
@Injectable()
export class MessagesState {
  @Action(AddMessage)
  addMessage(ctx: StateContext<Message[]>, { from, message }: AddMessage) {
    const state = ctx.getState();
    // omit `type` property that server socket sends
    ctx.setState([...state, { from, message }]);
  }
}
```

We are able to send messages to the server by dispatching the `SendWebSocketMessage` with the payload that you want to send to the server. Let's try it out:

```ts
@Component({ ... })
export class AppComponent {

  constructor(private store: Store) {}

  sendMessage(from: string, message: string) {
    const event = new SendWebSocketMessage({
      type: 'message',
      from,
      message
    });

    this.store.dispatch(event);
  }

}
```

When sending the message, remember the send is accepting a JSON-able object. The socket on the server side would be listening for the `message` event. For example, the server code could be as follows:

```ts
const { Server } = require('ws');
const { createServer } = require('http');

const app = require('express')();

const server = createServer(app);
const ws = new Server({ server });

server.listen(4200);

ws.on('connection', socket => {
  socket.on('message', data => {
    // That's the object that we passed into `SendWebSocketMessage` constructor
    const { type, from, message } = JSON.parse(data);

    if (type === 'message') {
      const event = JSON.stringify({
        type: '[Chat] Add message',
        from,
        message
      });

      // That's the same as `broadcast`
      // we want to send message to all connected
      // to the chat clients
      ws.clients.forEach(client => {
        client.send(event);
      });
    }
  });
});
```

Notice that you have to specify `type` property on server side, otherwise you will get an error - `Type ... not found on message`. If you don't want to use a property called `type` as the key then you can specify your own property name:

```ts
provideStore(
  [],
  withNgxsWebSocketPlugin({
    url: 'ws://localhost:4200',
    typeKey: 'myAwesomeTypeKey'
  })
);
```

Or with the module approach:

```ts
NgxsWebSocketPluginModule.forRoot({
  url: 'ws://localhost:4200',
  typeKey: 'myAwesomeTypeKey'
});
```

In order to kick off our websockets we have to dispatch the `ConnectWebSocket` action. This will typically happen at startup or if you need to authenticate before, after authentication is done. You can optionally pass the URL here.

```ts
@Component({ ... })
export class AppComponent {

  constructor(private store: Store) {}

  ngOnInit() {
    this.store.dispatch(new ConnectWebSocket());
  }

}
```

If you have difficulties with understanding how the plugin works, you can have a look at the data flow diagram below. From one side it seems a little bit complex, but no worries. Just follow the pink data flow that leads to the server-side starting from view:

![NGXS WebSocket data flow](/files/-LiFAEX-9RtvE7GIkVs0)

Here is a list of all the available actions you have:

* `ConnectWebSocket`: Dispatch this action when you want to init the web socket. Optionally pass URL here.
* `DisconnectWebSocket`: Dispatch this Action to disconnect a web socket.
* `WebSocketConnected`: Action dispatched when a web socket is connected.
* `WebSocketDisconnected`: Action dispatched when a web socket is disconnected. Use its handler for reconnecting.
* `SendWebSocketMessage`: Send a message to the server.
* `WebSocketMessageError`: Action dispatched by this plugin when an error ocurrs upon receiving a message.
* `WebSocketConnectionUpdated`: Action dispatched by this plugin when a new connection is created on top of an existing one. Existing connection is closing.

In summary - your server-side sockets should send objects that have a `type` property (or another key that you can provide in the `typeKey` property when calling `forRoot`). This plugin will receive a message from the server and dispatch the message as an action with the corresponding `type` value. If the `type` property doesn't match any client-side `@Action` methods (with an Action with the corresponding `static type` property value) then no State will respond to the message.


# Router

![Router Diagram](/files/-LBAhBYw-Tg4qDn2VOlC)

In the browser, the location (URL information) and session history (a stack of locations visited by the current browser tab) are stored in the global window object. They are accessible via:

* `window.location` ([Location API](https://developer.mozilla.org/en-US/docs/Web/API/Location))
* `window.history` ([History API](https://developer.mozilla.org/en-US/docs/Web/API/History))

Our location data is a dynamic and essential part of the application state-the kind of state that belongs in a store. Holding it in the store enables devtools luxuries like time-travel debugging, and easy access from any store-connected component.

This plugin binds that state from the Angular router to our NGXS store.

## Installation

```bash
npm i @ngxs/router-plugin

# or if you are using yarn
yarn add @ngxs/router-plugin

# or if you are using pnpm
pnpm i @ngxs/router-plugin
```

## Usage

When calling `provideStore`, include `withNgxsRouterPlugin` in your app config:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsRouterPlugin } from '@ngxs/router-plugin';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], withNgxsRouterPlugin())]
};
```

If you are still using modules, include the `NgxsRouterPluginModule` plugin in your root app module:

```ts
import { NgxsModule } from '@ngxs/store';
import { NgxsRouterPluginModule } from '@ngxs/router-plugin';

@NgModule({
  imports: [NgxsModule.forRoot([]), NgxsRouterPluginModule.forRoot()]
})
export class AppModule {}
```

Now the route will be reflected in your store under the `router` state name. The state is represented as a `RouterStateSnapshot` object.

You can also navigate using the store's dispatch method. It accepts the following arguments: `new Navigate(path: any[], queryParams?: Params, extras?: NavigationExtras)`. A simple example would be navigating to the admin page like this:

```ts
import { Store } from '@ngxs/store';
import { Navigate } from '@ngxs/router-plugin';

@Component({ ... })
export class MyApp {
  constructor(private store: Store) {}

  onClick() {
    this.store.dispatch(new Navigate(['/admin']))
  }
}
```

You can use action handlers to listen to state changes in your components and services by subscribing to the `RouterNavigation`, `RouterCancel`, `RouterError` or `RouterDataResolved` action classes.

## Listening to the data resolution event

You can listen for the `RouterDataResolved` action, which is dispatched when the navigated route has linked resolvers. For example:

```ts
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { Actions, ofActionSuccessful } from '@ngxs/store';
import { RouterDataResolved } from '@ngxs/router-plugin';

@Component({ ... })
export class AppComponent {
  constructor() {
    const actions$ = inject(Actions);

    actions$.pipe(
      ofActionSuccessful(RouterDataResolved),
      takeUntilDestroyed()
    ).subscribe((action: RouterDataResolved) => {
      console.log(action.routerState.root.firstChild.data);
    });
  }
}
```

The more explicit example would be a situation where you would want to bind an input property providing some resolved data. For example:

```ts
import { Actions, ofActionSuccessful } from '@ngxs/store';
import { RouterDataResolved } from '@ngxs/router-plugin';

import { map } from 'rxjs';

@Component({
  template: ` <app-some-component [data]="data$ | async"></app-some-component> `
})
export class AppComponent {
  data$ = inject(Actions).pipe(
    ofActionSuccessful(RouterDataResolved),
    map((action: RouterDataResolved) => action.routerState.root.firstChild.data)
  );
}
```

## Custom Router State Serializer

You can implement your own router state serializer to serialize the router snapshot:

```ts
import { Params, RouterStateSnapshot } from '@angular/router';

import { provideStore } from '@ngxs/store';
import { withNgxsRouterPlugin, RouterStateSerializer } from '@ngxs/router-plugin';

export interface RouterStateParams {
  url: string;
  params: Params;
  queryParams: Params;
}

// Map the router snapshot to { url, params, queryParams }
export class CustomRouterStateSerializer implements RouterStateSerializer<RouterStateParams> {
  serialize(routerState: RouterStateSnapshot): RouterStateParams {
    const {
      url,
      root: { queryParams }
    } = routerState;

    let { root: route } = routerState;
    while (route.firstChild) {
      route = route.firstChild;
    }

    const { params } = route;

    return { url, params, queryParams };
  }
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore([], withNgxsRouterPlugin()),
    { provide: RouterStateSerializer, useClass: CustomRouterStateSerializer }
  ]
};
```

Or with the module approach:

```ts
import { NgxsModule } from '@ngxs/store';
import { NgxsRouterPluginModule, RouterStateSerializer } from '@ngxs/router-plugin';

@NgModule({
  imports: [NgxsModule.forRoot([]), NgxsRouterPluginModule.forRoot()],
  providers: [{ provide: RouterStateSerializer, useClass: CustomRouterStateSerializer }]
})
export class AppModule {}
```

## Configuration

The `RouterNavigation` action is dispatched before guards and resolvers are run by default. Therefore the action handler may run too soon due to a navigation cancel by any guard or resolver. The `RouterNavigation` action may be run after all guards and resolvers by providing the `navigationActionTiming` configuration property:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsRouterPlugin, NavigationActionTiming } from '@ngxs/router-plugin';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsRouterPlugin({
        navigationActionTiming: NavigationActionTiming.PostActivation
      })
    )
  ]
};
```

Or with the module approach:

```ts
import { NgxsModule } from '@ngxs/store';
import { NgxsRouterPluginModule, NavigationActionTiming } from '@ngxs/router-plugin';

@NgModule({
  imports: [
    NgxsModule.forRoot([]),
    NgxsRouterPluginModule.forRoot({
      navigationActionTiming: NavigationActionTiming.PostActivation
    })
  ]
})
export class AppModule {}
```


# HMR

Hot Module Replacement (HMR) is a Webpack feature to update code in a running app without rebuilding it. This results in faster updates and less full page-reloads. In order to get HMR working with Angular CLI we first need to add a new environment and enable it.

> As of Angular v10, HMR is no longer supported and will be deprecated.
>
> As a workaround to keep store's state on full-page reloads you can use [`@ngxs/storage-plugin`](https://www.ngxs.io/plugins/storage). Here's a [basic implementation example](https://stackblitz.com/edit/ngxs-hmr-workaround-using-storage-plugin)

### Add environment for HMR

In this step we will configure the Angular CLI environments and define in which environment we enable HMR. We will start out by adding and changing files in the `src/environments/` directory. First we create a file called `src/environments/environment.hmr.ts` with the following contents:

```ts
export const environment = {
  production: false,
  hmr: true
};
```

Update `src/environments/environment.prod.ts` and add the hmr: false flag to the environment:

```ts
export const environment = {
  production: true,
  hmr: false
};
```

Lastly we edit `src/environments/environment.ts` and change the environment to:

```ts
export const environment = {
  production: false,
  hmr: false
};
```

Update angular.json to include an hmr environment as explained here and add configurations within build and serve to enable hmr. Note that \<project-name> here represents the name of the project you are adding this configuration to in angular.json.

```
  "build": {
    "configurations": {
      ...
      "hmr": {
        "fileReplacements": [
          {
            "replace": "src/environments/environment.ts",
            "with": "src/environments/environment.hmr.ts"
          }
        ]
      }
    }
  },
  ...
  "serve": {
    "configurations": {
      ...
      "hmr": {
        "hmr": true,
        "browserTarget": "<project-name>:build:hmr"
      }
    }
  }
```

Add the necessary types to src/tsconfig.app.json

```
{
  ...
  "compilerOptions": {
    ...
    "types": ["node"]
  },
}
```

Run ng serve with the flag --configuration hmr to enable hmr and select the new environment:

```bash
ng serve --configuration hmr
```

Create a shortcut for this by updating package.json and adding an entry to the script object:

```bash
"scripts": {
  ...
  "hmr": "ng serve --configuration hmr"
}
```

### Add dependency and configure app

In order to get HMR working we need to install the dependency and configure our app to use it.

Install the `@ngxs/hmr-plugin` package as a dev-dependency

Update src/main.ts to use the file we just created:

```ts
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { enableProdMode, NgModuleRef } from '@angular/core';

import { AppModule } from './app/app.module';
import { environment } from './environments/environment';

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

const bootstrap = () => platformBrowserDynamic().bootstrapModule(AppModule);

if (environment.hmr) {
  import('@ngxs/hmr-plugin').then(plugin => {
    plugin.hmr(module, bootstrap).catch((err: Error) => console.error(err));
  });
} else {
  bootstrap().catch((err: Error) => console.log(err));
}
```

The `@ngxs/hmr-plugin` should be loaded on demand using dynamic import thus this can benefit more readily from tree shaking.

### (OPTIONAL) Update src/app/app.module.ts to manage the state in HMR lifecycle:

```ts
import { StateContext } from '@ngxs/store';
import { NgxsHmrLifeCycle, NgxsHmrSnapshot as Snapshot } from '@ngxs/hmr-plugin';

@NgModule({ .. })
export class AppBrowserModule implements NgxsHmrLifeCycle<Snapshot> {
  public hmrNgxsStoreOnInit(ctx: StateContext<Snapshot>, snapshot: Partial<Snapshot>) {
    ctx.patchState(snapshot);
  }

  public hmrNgxsStoreBeforeOnDestroy(ctx: StateContext<Snapshot>): Partial<Snapshot> {
    return ctx.getState();
  }
}
```

### Starting the development environment with HMR enabled

Now that everything is set up we can run the new configuration:

```bash
npm run hmr
```

Example:

![hmr](/files/-LkQ3iflLA-1tSYnKwt7)

When starting the server Webpack will tell you that it’s enabled:

```bash
NOTICE Hot Module Replacement (HMR) is enabled for the dev server.
```

Now if you make changes to one of your components, those changes should be visible automatically without a complete browser refresh.

### HMR lifecycle

If you want to do some modifications to the state during the hmr lifecycle you can use these built-in actions. They will not be executed in production.

```ts
import { HmrInitAction, HmrBeforeDestroyAction } from '@ngxs/hmr-plugin';

@State({ ... })
@Injectable()
export class MyState {
  @Action(HmrInitAction)
  public hmrInit(ctx: StateContext, { payload }) {
    ctx.setState({ ... })
  }

  @Action(HmrBeforeDestroyAction)
  public hrmBeforeDestroy(ctx: StateContext, { payload }) {
    ctx.setState({ ... })
  }
}
```

### HMR Options

The following options are available:

* `autoClearLogs` - Clear logs after each refresh (default value is `true`).
* `deferTime` - Deferred time before loading the old state (default value is `100` ms);

```ts
import('@ngxs/hmr-plugin').then(plugin => {
  plugin
    .hmr(module, bootstrap, {
      deferTime: 100,
      autoClearLogs: true
    })
    .catch((err: Error) => console.error(err));
});
```

### HMR Utils

* `hmrIsReloaded` - returns `true` if the application was hot module replaced at least once or more.

Examples:

```ts
import { hmrIsReloaded } from '@ngxs/hmr-plugin';

@Component({})
class SomeComponent implements OnDestroy {
  ngOnDestroy(): void {
    if (hmrIsReloaded()) {
      return;
    }

    // heavy logic
  }
}
```


# RECIPES


# Authentication

Authentication is a common theme across many applications. Let's take a look at how we would implement this in NGXS.

First, let's define our state model and our actions:

```ts
export interface AuthStateModel {
  token: string | null;
  username: string | null;
}

export class Login {
  static readonly type = '[Auth] Login';

  constructor(public payload: { username: string; password: string }) {}
}

export class Logout {
  static readonly type = '[Auth] Logout';
}
```

In our state model, we want to track our token and the username. The token represents a JWT token that was issued for the session.

Let's hook up these actions in our state class and wire that up to our login service.

```ts
@State<AuthStateModel>({
  name: 'auth',
  defaults: {
    token: null,
    username: null
  }
})
@Injectable()
export class AuthState {
  @Selector()
  static getToken(state: AuthStateModel): string | null {
    return state.token;
  }

  @Selector()
  static getIsAuthenticated(state: AuthStateModel): boolean {
    return !!state.token;
  }

  constructor(private authService: AuthService) {}

  @Action(Login)
  login(ctx: StateContext<AuthStateModel>, action: Login) {
    return this.authService.login(action.payload).pipe(
      tap((result: { token: string }) => {
        ctx.patchState({
          token: result.token,
          username: action.payload.username
        });
      })
    );
  }

  @Action(Logout)
  logout(ctx: StateContext<AuthStateModel>) {
    const state = ctx.getState();
    return this.authService.logout(state.token).pipe(
      tap(() => {
        ctx.setState({
          token: null,
          username: null
        });
      })
    );
  }
}
```

In this state class, we have:

* A selector that will select the token from the store
* A login action method that will invoke the authentication service and set the token
* A logout action method that will invoke the authentication service and remove our state

Now let's wire up the state in our module.

```ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [AuthState],
      withNgxsStoragePlugin({
        keys: ['auth.token']
      })
    )
  ]
};
```

In a typical JWT setup, you want to store your token in the `localstorage`. To do this so we hookup our storage plugin and tell it to track the token key in our state.

Next, we want to make sure that our users can't go to any pages that require authentication. We can easily accomplish this with a router guard provided by Angular.

```ts
@Injectable()
export class AuthGuard implements CanActivate {
  constructor(private store: Store) {}

  canActivate() {
    const isAuthenticated = this.store.selectSnapshot(AuthState.getIsAuthenticated);
    return isAuthenticated;
  }
}
```

This guard will decide if a route can be activated by using our selector to select the token from the store. If the token is invalid it won't let the user go to that page. Let's make sure we implement this in our route itself by defining the `AuthGuard` in the `canActivate` definition.

```ts
export const routes: Routes = [
  {
    path: 'admin',
    loadComponent: () => import('./admin').then(m => m.AdminComponent),
    canActivate: [AuthGuard]
  }
];
```

A common action you want to take is when a user logs out, we want to actually redirect the user to the login page. We can use our action stream to listen to the `Logout` action and tell the router to go to the login page.

```ts
@Component({
  selector: 'app',
  template: '..'
})
export class AppComponent implements OnInit {
  constructor(
    private actions$: Actions,
    private router: Router
  ) {}

  ngOnInit() {
    this.actions$.pipe(ofActionDispatched(Logout)).subscribe(() => {
      this.router.navigate(['/login']);
    });
  }
}
```

And that's it!


# Caching

Caching requests executed by Actions is a common practice. NGXS does not provide this ability out of the box, but it is easy to implement.

There are many different ways to approach this. Below is a simple example of using the store's current values and returning them instead of calling the HTTP service.

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { tap } from 'rxjs';

export class GetNovels {
  static readonly type = '[Novels] Get novels';
}

@State<Novel[]>({
  name: 'novels',
  defaults: []
})
@Injectable()
export class NovelsState {
  constructor(private novelsService: NovelsService) {}

  @Action(GetNovels)
  getNovels(ctx: StateContext<Novel[]>) {
    return this.novelsService.getNovels().pipe(tap(novels => ctx.setState(novels)));
  }
}
```

Imagine that this state of novels contains only minimal information about them such as ID and name. When the user selects a particular novel - he is redirected to a page with full information about this novel. We want to load this information only once. Let's create a state and call it `novelsInfo`, this will be the object whose keys are the identifiers of the novels:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext, createSelector } from '@ngxs/store';
import { tap } from 'rxjs';

export interface NovelsInfoStateModel {
  [key: string]: Novel;
}

export class GetNovelById {
  static readonly type = '[Novels info] Get novel by ID';
  constructor(public id: string) {}
}

@State<NovelsInfoStateModel>({
  name: 'novelsInfo',
  defaults: {}
})
@Injectable()
export class NovelsInfoState {
  static getNovelById(id: string) {
    return createSelector([NovelsInfoState], (state: NovelsInfoStateModel) => state[id]);
  }

  constructor(private novelsService: NovelsService) {}

  @Action(GetNovelById)
  getNovelById(ctx: StateContext<NovelsInfoStateModel>, action: GetNovelById) {
    const novels = ctx.getState();
    const id = action.id;

    if (novels[id]) {
      // If the novel with ID has been already loaded
      // we just break the execution
      return;
    }

    return this.novelsService.getNovelById(id).pipe(
      tap(novel => {
        ctx.patchState({ [id]: novel });
      })
    );
  }
}
```

The component responsible for displaying information about the novel can subscribe to the `params` observable of the `ActivatedRoute` to listen for changes in the parameters. The code will appear as follows:

```ts
@Component({
  selector: 'app-novel',
  template: `
    @if (novel(); as novel) {
      <h1>{{ novel.title }}</h1>
      <span>{{ novel.author }}</span>
      <p>
        {{ novel.content }}
        <del datetime="{{ novel.publishedAt }}"></del>
      </p>
    }
  `,
  standalone: true
})
export class NovelComponent {
  novel = signal<Novel | null>(null);

  constructor(route: ActivatedRoute, store: Store) {
    route.params
      .pipe(
        switchMap(params =>
          store
            .dispatch(new GetNovelById(params.id))
            .pipe(mergeMap(() => store.select(NovelsInfoState.getNovelById(params.id))))
        ),
        takeUntilDestroyed()
      )
      .subscribe(novel => {
        this.novel.set(novel);
      });
  }
}
```

In this example, we're utilizing `switchMap`, so if the user navigates to another novel and the `params` observable emits a new value, we need to complete the previously started asynchronous job, which, in our case, involves fetching the novel by its ID.


# Component Events from NGXS

Developers always use the `@Output` decorator in conjunction with the `EventEmitter`. The below code has been seen by any Angular developer:

```ts
@Output() search = new EventEmitter<string>();
```

The secret is that the `@Output` can decorate any "observable" property. The Angular compiler emits needful information for the Angular itself that says "hey, please subscribe to the `search` class property and dispatch `CustomEvent` any time the observable emits".

Let's imagine that we're a part of the A team. We develop custom element that uses NGXS and we want to provide this component to the team B. The team B doesn't know anything about NGXS, they cannot use our API. Our element is just a black box that exposes data via `@Output`.

We develop the `app-email-list` custom element that emits `messagesLoaded` DOM event and gives the data to the team B for analytics. Given the following code:

```ts
@Component({
  selector: 'app-email-list',
  template: `
    @for (message of messages(); track message) {
      <app-message [message]="message" />
    }

    <app-button (click)="refresh()">Refresh messages</app-button>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [MessageComponent, ButtonComponent]
})
export class EmailListComponent {
  messages: Signal<Message[]> = this.store.selectSignal(MessagesState.getMessages);

  @Output() messagesLoaded = new EventEmitter<Message[]>();

  constructor(private store: Store) {}

  refresh(): void {
    this.store.dispatch(new LoadMessages()).subscribe(() => {
      const messages = this.store.selectSnapshot(MessagesState.getMessages);
      this.messagesLoaded.emit(messages);
    });
  }
}
```

The above code is very simple and is used for demonstrating purposes only! As you can see we dispatch the `LoadMessages` action every time the user clicks "Refresh messages" button. After the `LoadMessages` action handler has completed his asynchronous job we emit the `messagesLoaded` event. Let's be more declarative:

```ts
@Component({
  selector: 'app-email-list',
  template: `
    @for (message of messages(); track message) {
      <app-message [message]="message" />
    }

    <app-button (click)="refresh()">Refresh messages</app-button>
  `,
  changeDetection: ChangeDetectionStrategy.OnPush,
  standalone: true,
  imports: [MessageComponent, ButtonComponent]
})
export class EmailListComponent {
  messages: Signal<Message[]> = this.store.selectSignal(MessagesState.getMessages);

  button = viewChild.required(ButtonComponent);

  @Output() messagesLoaded = toObservable(this.button).pipe(
    first(Boolean),
    mergeMap(() => this.button().click),
    switchMap(() => this.store.dispatch(new LoadMessages())),
    map(() => this.store.selectSnapshot(MessagesState.getMessages))
  );

  constructor(private store: Store) {}
}
```

Assume that `ButtonComponent.click` is an `EventEmitter`. Wow, we've done it in a more declarative and reactive way. So every time the user clicks the `app-button` our `switchMap` will produce the next `store.dispatch` subscribe and unsubscribe from the previous one. Next we use the `map` operator that will map our stream value to the `Message[]` array from our state.

Now let's take away that idea with A and B teams. As our store is a single source of truth thus we can listen to any action from any part of our application. DOM events can be handy to use with the `Actions` stream. Assume we've got a component that emits `booksLoaded` event every time when different genre of books are loaded:

```ts
// books.state.ts
const enum Genre {
  Novel,
  Detective,
  Horror
}

export class LoadBooks {
  static readonly type = '[Books] Load books';
  constructor(public genre: Genre) {}
}

export class BooksState {
  static getBooks(genre: Genre) {
    return createSelector([BooksState], (books: Book[]) =>
      books.filter(book => book.genre === genre)
    );
  }
}

// books.component.ts
export class BooksComponent {
  @Output() booksLoaded = this.actions$.pipe(
    ofActionSuccessful(LoadBooks),
    map((action: LoadBooks) => this.store.selectSnapshot(BooksState.getBooks(action.genre)))
  );

  constructor(
    private store: Store,
    private actions$: Actions
  ) {}
}
```

This might significantly reduce your code business logic and do it in a more declarative and reactive way.


# Debouncing Actions

There are situations when there is a need to debounce dispatched actions and reduce requests send to our API. Let's consider a simple application that renders a list of news and provides the ability to search among all of them:

```ts
class SearchNews {
  static readonly type = '[News] Search news';

  constructor(public title: string) {}
}

@Component({
  selector: 'app-news-portal',
  template: `
    <app-news-search [lastSearchedTitle]="lastSearchedTitle()" (search)="search($event)" />
    <app-news [news]="news()" />
  `,
  standalone: true,
  imports: [NewsSearchComponent, NewsComponents]
})
export class NewsPortalComponent {
  news: Signal<News[]> = this.store.selectSignal(NewsState.getNews);

  lastSearchedTitle = this.store.selectSignal(NewsState.getLastSearchedTitle);

  constructor(
    private store: Store,
    actions$: Actions
  ) {
    actions$
      .pipe(
        ofActionDispatched(SearchNews),
        map((action: SearchNews) => action.title),
        debounceTime(2000),
        takeUntilDestroyed()
      )
      .subscribe(title => {
        store.dispatch(new GetNews(title));
      });
  }

  search(title: string): void {
    this.store.dispatch(new SearchNews(title));
  }
}
```

In the above example we've got the `app-news-portal` component that listens to the `search` event, dispatched by the `app-news-search` component. The `search` method, invoked on the `search` event, dispatches the `SearchNews` action. Notice that the `SearchNews` action is defined in the component file because it's never used by any other part of the application. We don't want to overload our server with requests thus we listen to the `Actions` stream that pipes the `SearchNews` action with `debounceTime` operator. Let's look at the below code of how we would implement our `NewsState`:

```ts
export interface NewsStateModel {
  news: News[];
  lastSearchedTitle: string | null;
}

export class GetNews {
  static readonly type = '[News] Get news';
  constructor(public title = '') {}
}

@State<NewsStateModel>({
  name: 'news',
  defaults: {
    news: [],
    lastSearchedTitle: null
  }
})
@Injectable()
export class NewsState {
  @Selector()
  static getNews(state: NewsStateModel): News[] {
    return state.news;
  }

  @Selector()
  static getLastSearchedTitle(state: NewsStateModel): string | null {
    return state.lastSearchedTitle;
  }

  constructor(private http: HttpClient) {}

  @Action(GetNews)
  getNews(ctx: StateContext<NewsStateModel>, { title }: GetNews) {
    return this.http.get<News[]>(`/api/news?search=${title}`).pipe(
      tap(news => {
        ctx.setState({ news, lastSearchedTitle: title });
      })
    );
  }
}
```

The above state is pretty simple. As you can see we don't create an action handler for the `SearchNews` but it still will be passed via `Actions` stream and debounced. It all depends on the task in practice but you're already informed about debouncing actions.

## Alternative Approach: Using cancelUncompleted

Instead of debouncing in the component, you can use the `cancelUncompleted` option with the `abortSignal` (available in v21+) to automatically cancel previous search requests:

```ts
@Component({
  selector: 'app-news-portal',
  template: `
    <app-news-search [lastSearchedTitle]="lastSearchedTitle()" (search)="search($event)" />
    <app-news [news]="news()" />
  `,
  standalone: true,
  imports: [NewsSearchComponent, NewsComponents]
})
export class NewsPortalComponent {
  news = this.store.selectSignal(NewsState.getNews);
  lastSearchedTitle = this.store.selectSignal(NewsState.getLastSearchedTitle);

  constructor(private store: Store) {}

  search(title: string): void {
    // Dispatch directly - cancellation is handled by the state
    this.store.dispatch(new GetNews(title));
  }
}
```

```ts
@State<NewsStateModel>({
  name: 'news',
  defaults: {
    news: [],
    lastSearchedTitle: null
  }
})
@Injectable()
export class NewsState {
  @Selector()
  static getNews(state: NewsStateModel): News[] {
    return state.news;
  }

  @Selector()
  static getLastSearchedTitle(state: NewsStateModel): string | null {
    return state.lastSearchedTitle;
  }

  constructor(private http: HttpClient) {}

  @Action(GetNews, { cancelUncompleted: true })
  async getNews(ctx: StateContext<NewsStateModel>, { title }: GetNews) {
    try {
      // Pass abortSignal to automatically cancel previous requests
      const response = await fetch(`/api/news?search=${title}`, {
        signal: ctx.abortSignal
      });

      const news = await response.json();
      ctx.setState({ news, lastSearchedTitle: title });
    } catch (error) {
      if (error.name === 'AbortError') {
        return; // Gracefully handle cancellation
      }
      throw error;
    }
  }
}
```

This approach is simpler as it moves the cancellation logic into the state where it belongs, and automatically cancels in-flight HTTP requests when a new search is dispatched. You can still combine this with debouncing in the component if you want to delay the dispatch itself.


# Dynamic Plugins

Please refer to this [guide](https://angular.io/guide/build#configure-environment-specific-defaults) if you haven't set up environment files yet.

Angular provides the ability to have a different environment file loaded for development as compared to production or other build targets. We can use this to improve our application bundling when it comes to development only packages. In NGXS the packages that are mainly useful only for development mode are the `@ngxs/devtools-plugin` and `@ngxs/logger-plugin`. Typically you would only want to use these packages during development and not in production.

Let's look at the code below:

```ts
// environment.ts
import { withNgxsLoggerPlugin } from '@ngxs/logger-plugin';
import { withNgxsReduxDevtoolsPlugin } from '@ngxs/devtools-plugin';

export const environment = {
  production: false,
  plugins: [withNgxsLoggerPlugin(), withNgxsReduxDevtoolsPlugin()]
};
```

This means that these plugins will be used only when Angular uses `environment.ts` file, but in the production build it will be replaced with `environment.prod.ts` file (or any other configuration you use). If you already figured out the `environment.prod.ts` file will contain `plugins` property that equals empty array, the code would look as follows:

```ts
// environment.prod.ts
export const environment = {
  production: true,
  plugins: []
};
```

All we have left to do is to import the environment file and reference `plugins` property in the app config `provideStore()`:

```ts
import { provideStore } from '@ngxs/store';
import { withNgxsRouterPlugin } from '@ngxs/router-plugin';

import { environment } from '../environments/environment';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], ...[withNgxsRouterPlugin(), ...environment.plugins])]
};
```

This approach will reduce your production bundle size, as these packages are only needed during development.

## Runtime Registration with `registerNgxsPlugin`

For cases where you need to register a plugin imperatively at runtime — for example, based on a feature flag or after lazy-loading a module — use `registerNgxsPlugin` instead of the environment-file approach:

```ts
import { Component } from '@angular/core';
import { registerNgxsPlugin } from '@ngxs/store';
import { MyDevtoolsPlugin } from './plugins/devtools.plugin';

@Component({
  selector: 'app-root',
  template: '...'
})
export class AppComponent {
  constructor() {
    if (ngDevMode) {
      registerNgxsPlugin(MyDevtoolsPlugin);
    }
  }
}
```

The plugin is automatically cleaned up when the component (or any injection context) is destroyed. See the [Plugins](/plugins#dynamic-plugin-registration) overview for full API details.


# Module Federation

Module Federation with `webpack 5` enables angular for a seamless Microfrontend experience. Using NGXS in this context is as simple as in any other angular application. But there are some things to keep in mind.

This guide is based on `@angular/core@12.2.5` which uses `webpack@5.50.0` and [@angular-architects/module-federation@12.4.0](https://www.npmjs.com/package/@angular-architects/module-federation).

## Sharing Dependencies

In module federation with `webpack 5`, it is possible to share dependencies between the Microfrontends. This is useful for dependencies like the angular runtime, which does not need to be reloaded and executed for each Microfrontend. For this purpose, each Microfrontend specifies which dependencies it has and is willing to share with others.

For this purpose, the dependencies are specified in the shared object in `webpack.config.js`. This also applies to NGXS libraries. It is important that `singleton: true` is specified. It is recommended to share `rxjs` as well.

> Module federation should work a LOT better with the @dev tagged version of NGXS. But it is also possible to use the latest stable version (3.7.2).

```js
plugins: [
  new ModuleFederationPlugin({
    name: 'mfOne',
    filename: 'remoteEntry.js',
    exposes: {
      './mfModuleX': './apps/mfOne/src/app/x/x.module.ts',
      './mfModuleY': './apps/mfOne/src/app/y/y.module.ts'
    },

    shared: share({
      '@angular/core': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
      '@angular/common': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
      '@angular/common/http': {
        singleton: true,
        strictVersion: true,
        requiredVersion: 'auto'
      },
      '@angular/router': { singleton: true, strictVersion: true, requiredVersion: 'auto' },
      '@ngxs/devtools-plugin': {
        singleton: true,
        strictVersion: true,
        requiredVersion: '3.7.2'
      },
      '@ngxs/store': { singleton: true, strictVersion: true, requiredVersion: '3.7.2' },
      rxjs: { singleton: true, strictVersion: true, requiredVersion: '6.6.7' },

      ...sharedMappings.getDescriptors()
    })
  }),
  sharedMappings.getPlugin()
];
```

## Into libraries

Code, that is not shared, will be reinitiated, when a module is loaded. This is also true for angular services. In case of NGXS, this will be a problem. Every state is only allowed once and try's to register itself in the root store. If the same state comes from multiples Microfrontends, or the same Microfrontend, but with from different places will result in an error.

To solve the problem, the state can be moved to a library. This is particularly useful in applications that are developed with `nx`. These libraries can then be shared in the same way as libraries from the previous example.

```js
plugins: [
  new ModuleFederationPlugin({
    // ...
    shared: share({
      // ...
      '@project/shared/utils': { singleton: true, import: 'libs/shared/utils/src/index' },
      '@project/usecase/domain': { singleton: true, import: 'libs/usecase/domain/src/index' }
      // ...
    })
  })
];
```

## Stand alone

With module federation, the Microfrontends can also run on their own. For this case, an entry module is needed, which must not be exported in the `webpack.config.js`. In this module, all `.forRoot()` modules are imported, e.g. the `Router` or `NgxsModule.forRoot()`.

The standalone mode can be used for end-to-end tests. It is also a good idea to use the standalone mode for debugging.

If the application should not run in standalone mode, this is not needed.

In the article [Using Module Federation with (Nx) Monorepos and Angular](https://www.angulararchitects.io/en/aktuelles/using-module-federation-with-monorepos-and-angular/) by Manfred Steyer, from the module federation article series, it goes a bit deeper into the details of sharing libraries.

## Resources

You can find an example application [here](https://github.com/adrian-goe/bachelorarbeit-demo).


# Unit Testing

Unit testing NGXS states is similar to testing other services. To perform a unit test, we need to set up a store with the states against which we want to make assertions. Then, we dispatch actions, listen to changes, and perform expectations.

A basic test looks as follows:

```ts
// zoo.state.spec.ts
import { TestBed } from '@angular/core/testing';
import { provideStore } from '@ngxs/store';

import { ZooState } from './zoo.state';
import { FeedAnimals } from './zoo.actions';

describe('Zoo', () => {
  let store: Store;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [provideStore([ZooState])]
    });

    store = TestBed.inject(Store);
  });

  it('it toggles feed', () => {
    store.dispatch(new FeedAnimals());

    const feed = store.selectSnapshot(ZooState.getFeed);
    expect(feed).toBe(true);
  });
});
```

We recommend using the `selectSnapshot` or `selectSignal` methods instead of `select` or `selectOnce`, because it would require calling a `done` function manually. This actually depends on whether states are updated synchronously or asynchronously. If states are updated synchronously, then `selectOnce` would always emit updated state synchronously.

> 💡 `selectSnapshot` may behave similarly to `selectSignal`, but it would be more readable because you don't need to call the signal function to get the value.

Given the following example:

```ts
it('should select feed', () => {
  store.selectOnce(ZooState.getFeed).subscribe(feed => {
    expect(feed).toBeTruthy();
  });

  const feed = store.selectSnapshot(ZooState.getFeed);
  expect(feed).toBeTruthy();
});
```

If you're using Jest, you may use [`expect.assertions`](https://jestjs.io/docs/expect#expectassertionsnumber) to let Jest know that a certain amount of assertions must run within the test:

```ts
it('should select feed', () => {
  expect.assertions(1);

  store.selectOnce(ZooState.getFeed).subscribe(feed => {
    expect(feed).toBeTruthy();
  });
});
```

The above test would fail if the expectation within the subscribe function isn't run once.

## Prepping State

Often in your app, you'll need to test what happens when the state is C and you dispatch action X. You can use `store.reset(MyNewState)` to prepare the state for your next operation.

> ⚠️ When resetting the state, ensure you provide the registered state name as the key. `store.reset` affects your entire state. Merge the current state with your new changes to ensure nothing gets lost.

```ts
import { TestBed } from '@angular/core/testing';

export const SOME_DESIRED_STATE = {
  animals: ['Panda']
};

describe('Zoo', () => {
  let store: Store;

  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [provideStore([ZooState])]
    });

    store = TestBed.inject(Store);
    store.reset({
      ...store.snapshot(),
      zoo: SOME_DESIRED_STATE
    });
  });

  it('it toggles feed', () => {
    store.dispatch(new FeedAnimals());

    const feed = store.selectSnapshot(ZooState.getFeed);
    expect(feed).toBe(true);
  });
});
```

## Testing Selectors

Selectors are simply plain functions that accept the state as an argument, making them easy to test. A simple test might look like this:

```ts
import { TestBed } from '@angular/core/testing';

describe('Zoo', () => {
  it('it should select pandas', () => {
    const pandas = store.selectSnapshot(ZooState.getPandas);
    expect(pandas).toEqual(['pandas']);
  });
});
```

In your application you may have selectors created dynamically using the `createSelector` function:

```ts
export class ZooSelectors {
  static getAnimalNames = (type: string) => {
    return createSelector([ZooState], (state: ZooStateModel) =>
      state.animals.filter(animal => animal.type === type).map(animal => animal.name)
    );
  };
}
```

Testing these selectors is really easy. You just need to mock the state and pass it as a parameter to our selector:

```ts
it('should select requested animal names from state', () => {
  const zooState = {
    animals: [
      { type: 'zebra', name: 'Andy' },
      { type: 'panda', name: 'Betty' },
      { type: 'zebra', name: 'Crystal' },
      { type: 'panda', name: 'Donny' }
    ]
  };

  const value = ZooSelectors.getAnimalNames('zebra')(zooState);

  expect(value).toEqual(['Andy', 'Crystal']);
});
```

## Testing Asynchronous Actions

It's also very easy to test asynchronous actions. You can use `async/await` along with RxJS's `firstValueFrom` method, which "converts" Observables to Promises. Alternatively, you can use a `done` callback.

The example below isn't really complex, but it clearly demonstrates how to test asynchronous code using `async/await`:

```ts
import { timer, tap, mergeMap } from 'rxjs';

it('should wait for completion of the asynchronous action', async () => {
  class IncrementAsync {
    static type = '[Counter] Increment async';
  }

  class DecrementAsync {
    static type = '[Counter] Decrement async';
  }

  // Assume you will make some XHR call to your API or anything else
  function getRandomDelay() {
    return 1000 * Math.random();
  }

  @State({
    name: 'counter',
    defaults: 0
  })
  @Injectable()
  class CounterState {
    @Selector()
    static getCounter(state: number) {
      return state;
    }

    @Action(IncrementAsync)
    incrementAsync(ctx: StateContext<number>) {
      const delay = getRandomDelay();

      return timer(delay).pipe(
        tap(() => {
          // We're incrementing the state value and setting it
          ctx.setState(state => (state += 1));
        }),
        // After incrementing we want to decrement it again to the zero value
        mergeMap(() => ctx.dispatch(new DecrementAsync()))
      );
    }

    @Action(DecrementAsync)
    decrementAsync(ctx: StateContext<number>) {
      const delay = getRandomDelay();

      return timer(delay).pipe(
        tap(() => {
          ctx.setState(state => (state -= 1));
        })
      );
    }
  }

  TestBed.configureTestingModule({
    providers: [provideStore([CounterState])]
  });

  const store: Store = TestBed.inject(Store);

  await firstValueFrom(store.dispatch(new IncrementAsync()));

  const counter = store.selectSnapshot(CounterState.getCounter);
  expect(counter).toBe(0);
});
```

## Collecting Actions

Below is the code used to collect actions passing through the actions stream:

```ts
import {
  ENVIRONMENT_INITIALIZER,
  inject,
  Injectable,
  makeEnvironmentProviders,
  OnDestroy
} from '@angular/core';
import { Actions, ActionStatus, ActionContext } from '@ngxs/store';
import { ReplaySubject, Subject, takeUntil } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class NgxsActionCollector implements OnDestroy {
  private _destroyed$ = new ReplaySubject<void>(1);
  private _stopped$ = new Subject<void>();
  private _started = false;

  readonly dispatched: any[] = [];
  readonly completed: any[] = [];
  readonly successful: any[] = [];
  readonly errored: any[] = [];
  readonly cancelled: any[] = [];

  constructor(private _actions$: Actions) {}

  start() {
    if (this._started) {
      return;
    }
    this._started = true;
    this._actions$.pipe(takeUntil(this._destroyed$), takeUntil(this._stopped$)).subscribe({
      next: (actionCtx: ActionContext) => {
        switch (actionCtx.status) {
          case ActionStatus.Dispatched:
            this.dispatched.push(actionCtx.action);
            break;
          case ActionStatus.Successful:
            this.successful.push(actionCtx.action);
            this.completed.push(actionCtx.action);
            break;
          case ActionStatus.Errored:
            this.errored.push(actionCtx.action);
            this.completed.push(actionCtx.action);
            break;
          case ActionStatus.Canceled:
            this.cancelled.push(actionCtx.action);
            this.completed.push(actionCtx.action);
            break;
          default:
            break;
        }
      },
      complete: () => {
        this._started = false;
      },
      error: () => {
        this._started = false;
      }
    });
  }

  reset() {
    function clearArray(arr: any[]) {
      arr.splice(0, arr.length);
    }
    clearArray(this.dispatched);
    clearArray(this.completed);
    clearArray(this.successful);
    clearArray(this.errored);
    clearArray(this.cancelled);
  }

  stop() {
    this._stopped$.next();
  }

  ngOnDestroy(): void {
    this._destroyed$.next();
  }
}

export function provideNgxsActionCollector() {
  return makeEnvironmentProviders([
    {
      provide: ENVIRONMENT_INITIALIZER,
      multi: true,
      useValue: () => inject(NgxsActionCollector).start()
    }
  ]);
}
```

The actions collector snippet above was created by the NGXS team and has been successfully used in production apps for years. Now, let's examine an example of how to set up the collector and how to use it:

```ts
describe('Zoo', () => {
  const testSetup = () => {
    TestBed.configureTestingModule({
      providers: [provideStore([ZooState]), provideNgxsActionCollector()]
    });

    const store = TestBed.inject(Store);
    const actionCollector = TestBed.inject(NgxsActionCollector);
    const actionsDispatched = actionCollector.dispatched;

    return { store, actionsDispatched };
  };

  it('it toggles feed', () => {
    const { store, actionsDispatched } = testSetup();

    store.dispatch(new FeedAnimals());

    expect(actionsDispatched.some(action => action instanceof FeedAnimals)).toBeTruthy();
  });
});
```

When using [Jest's `expect.extend`](https://jestjs.io/docs/expect#expectextendmatchers), we can even add our custom matcher to Jest for assertions against dispatched actions:

```ts
// src/matchers.ts
expect.extend({
  toHaveBeenDispatched(expected: any | any[], actionCollector: NgxsActionCollector) {
    if (!actionCollector) {
      return {
        pass: false,
        message: () => `actionCollector is ${actionCollector}.`
      };
    }

    const verifyActionFn = (expectedAction: any) => {
      return actionCollector.dispatched.some(
        actionDispatched =>
          expectedAction.constructor === actionDispatched.constructor &&
          this.equals(actionDispatched, expectedAction)
      );
    };
    const actionsToCheck = Array.isArray(expected) ? expected : [expected];
    const notDispatchedActions = actionsToCheck.filter(
      (expectedAction: any) => !verifyActionFn(expectedAction)
    );

    return {
      pass: notDispatchedActions.length === 0,
      message: () =>
        `Actions:` +
        notDispatchedActions.map(
          action => `\n${action?.constructor?.name} ${this.utils.stringify(action)}`
        ) +
        `\nnot found among dispatched actions.`
    };
  }
});

declare global {
  namespace jest {
    interface Matchers<R> {
      toHaveBeenDispatched(actionCollector: NgxsActionCollector): boolean;
    }
  }
}
```

To make that matcher available in your unit tests, you can provide it in [`setupFilesAfterEnv`](https://jestjs.io/docs/configuration#setupfilesafterenv-array):

```ts
// jest.config.ts
export default {
  // Some other configuration options...
  setupFilesAfterEnv: ['<rootDir>/src/matchers.ts']
};
```

Here's a simple example of how to use that matcher:

```ts
describe('Zoo', () => {
  const testSetup = () => {
    TestBed.configureTestingModule({
      providers: [provideStore([ZooState]), provideNgxsActionCollector()]
    });

    const store = TestBed.inject(Store);
    const actionCollector = TestBed.inject(NgxsActionCollector);

    return { store, actionCollector };
  };

  it('it should get animals and dispatch success action', async () => {
    const { store, actionCollector } = testSetup();

    await firstValueFrom(store.dispatch(new GetAnimals()));

    // Consider `GetAnimalsSuccess` as an action dispatched within
    // the `GetAnimals` action handler after animals have been
    // successfully loaded:
    // return someService.getAnimals().pipe(
    //   tap(() => ctx.dispatch(new GetAnimalsSuccess()))
    // )
    expect(new GetAnimalsSuccess()).toHaveBeenDispatched(actionCollector);
  });
});
```


# RxAngular Integration

There are use cases when is desired to have a transient component state has it's lifetime bound to the component lifecycle. [RxAngular](https://github.com/rx-angular/rx-angular) provides a solution for this problem that is fully reactive and with focus on runtime performance and template rendering.

In order to leverage this library and all the power of a global state management is possible to integrate RxAngular with NGXS. First, let's bind a value from NGXS state to RxAngular component state:

```ts
interface HeroesComponentState {
  heroes: Hero[];
}

const initHeroesComponentState: Partial<HeroesComponentState> = {
  heroes: []
};

@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css'],
  providers: [RxState] // <--- This binds RxState to the lifetime of the component
})
export class HeroesComponent {
  heroes: Hero[];

  readonly heroes$: Observable<Hero[]> = this.state.select('heroes');

  constructor(
    store: Store,
    private state: RxState<HeroesComponentState>
  ) {
    const stateHeroes$ = store.select(getHeroes);

    this.state.set(initHeroesComponentState);
    this.state.connect('heroes', stateHeroes$); // <--- Here we connect NGXS with RxAngular
  }
}
```

It is also important to connect the changes on the component local state to NGXS. For example, let's bind the addHero and deleteHero on the following code:

```ts
@Component({
  selector: 'app-heroes',
  templateUrl: './heroes.component.html',
  styleUrls: ['./heroes.component.css'],
  providers: [RxState]
})
export class HeroesComponent {
  heroes: Hero[];

  readonly add = new Subject<string>();
  readonly delete = new Subject<Hero>();

  constructor(
    private state: RxState<HeroesComponentState>,
    private store: Store
  ) {
    this.state.hold(
      // <--- RxAngular hold will manage the subscription for us
      this.add.pipe(switchMap(name => this.store.dispatch(new AddHero(name)))) // <--- dispatch action to NGXS
    );

    this.state.hold(
      this.delete.pipe(switchMap(hero => this.store.dispatch(new DeleteHero(hero))))
    );
  }
}
```

That's it! The advantage of this approach is that you can leverage all the reactivity from RxAngular and still manage your global state using NGXS. This allows you to combine the best of both libraries.

To check a full example integrating NGXS with RxAngular checkout this Tour of Heroes example [here](https://github.com/rx-angular/rx-angular/tree/master/apps/tour-of-heroes-ngxs)


# Zoneless Server-Side Rendering

When zone.js is disabled, Angular lacks awareness of currently executing tasks. However, it provides a built-in service called [`PendingTasks`](https://angular.dev/api/core/ExperimentalPendingTasks). When making an HTTP request through the `HttpClient`, Angular adds a pending task until the request is completed. This information is valuable for determining when the app becomes stable, as stability knowledge is essential for both server-side rendering and hydration features.

During server-side rendering, the HTML content is not serialized until `appRef.isStable` emits for the first time. `isStable` doesn't emit until there are no pending tasks, indicating that all asynchronous operations, such as HTTP requests, have completed.

NGXS also executes actions during server-side rendering, and some of these actions may be asynchronous. When zone.js is disabled, the content will be serialized before these actions complete. This means that the server-side rendering process may capture an incomplete or inconsistent state of the application if asynchronous actions are not completed before the content is serialized.

Let's examine the recipe for updating the "pending tasks" state whenever any action is dispatched and completed:

```ts
import { ApplicationConfig } from '@angular/core';
import { provideStore, withNgxsPendingTasks } from '@ngxs/store';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], withNgxsPendingTasks())]
};
```


# Lazy Loading Action Handlers

NGXS actions can sometimes become large or require code-splitting due to application size. The `callAsync()` utility allows you to dynamically load and run action logic only when it's needed — improving bundle size and startup performance.

The `callAsync()` helper makes it easy to lazy-load action handler modules, run operations inside the Angular injector context when needed, and handle async, observable, or synchronous results seamlessly.

````ts
import {
  DestroyRef,
  ɵisPromise,
  runInInjectionContext,
  type EnvironmentInjector
} from '@angular/core';
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { EMPTY, from, isObservable, Observable, of, switchMap } from 'rxjs';

export interface CallAsyncParams<T> {
  injector: EnvironmentInjector;
  actionLoader: () => Promise<T>;
  asyncOperation: (impl: T) => Promise<void> | Observable<unknown> | void;
}

/**
 * This function is intended for use within NGXS actions, which may load
 * other action handlers asynchronously.
 *
 * The signature is the following:
 *
 * ```ts
 * return callAsync({
 *   injector: this._environmentInjector,
 *   actionLoader: () => import('./action-handlers/validate-store-payment'),
 *   asyncOperation: (m) => m.validateStorePayment(ctx, this._store, action),
 * });
 * ```
 */
export function callAsync<T>(params: CallAsyncParams<T>) {
  if (params.injector.destroyed) {
    return EMPTY;
  }

  const destroyRef = params.injector.get(DestroyRef);

  return from(params.actionLoader()).pipe(
    switchMap(impl => {
      const result = runInInjectionContext(params.injector, () => params.asyncOperation(impl));

      // If the `asyncOperation` is asynchronous and requires the inner
      // observable to be subscribed to, we then return it to `switchMap`.
      if (isObservable(result) || ɵisPromise(result)) {
        return result;
      }

      return of(undefined);
    }),
    takeUntilDestroyed(destroyRef)
  );
}
````

## Usage

In the example below, `validate-store-payment.ts` is only loaded when the `ValidateStorePayment` action is dispatched. The module exports a `validateStorePayment()` function that contains the actual logic, so users who never trigger this action pay no bundle cost for it.

```ts
export class MyState {
  private _injector = inject(EnvironmentInjector);

  @Action(ValidateStorePayment)
  validateStorePayment(ctx: StateContext<StateModel>, action: ValidateStorePayment) {
    return callAsync({
      injector: this._injector,
      actionLoader: () => import('./action-handlers/validate-store-payment'),
      asyncOperation: m => m.validateStorePayment(ctx, action)
    });
  }
}
```

```ts
// action-handlers/validate-store-payment.ts

export function validateStorePayment(
  ctx: StateContext<StateModel>,
  action: ValidateStorePayment
) {
  const service = inject(MyService);

  return service.doSomeAsyncStuff(...);
}
```

## Directory Structure Suggestion

```
states/
├── my.state.ts
├── action-handlers/
│   └── validate-store-payment.ts ← lazy-loaded
```


# COMMUNITY


# FAQ

## Can I use NGXS with Angular 5?

3.x supports Angular 6 and RxJs 6 out of the box. However, you can still use it with Angular 5 by upgrading your RxJs version and using the RxJs compatibility package in your project.

## Is this ready for production?

Yes, we made a huge effort with 2.0 to ensure stability and good test coverage. There are several individuals who are using this in production today.

## Could we not reduce the boilerplate more by just calling the method directly?

The main goal of NGXS is to make state management easy with as little boilerplate as possible. The question is often raised that we could reduce the boilerplate even more by just letting you call the method on the state rather than having action classes to dispatch. This is not really possible to do and keep a global state with rich debugging and hot reload capability. When we invoke a function we have to go to the global state and slice out that portion and pass it to the method. There is no good way to do this when calling methods directly. Additionally by using action dispatching, you can share actions between states and higher order states very easily.


# Resources

### Projects

* [Angular Authentication and Authorization flows with NGXS](https://github.com/nikosanif/angular-authentication)
* [Angular 6 with NGXS and NX](https://xmlking.github.io/ngx-starter-kit/home)
* [Angular 7, Angular Material and NGXS](https://github.com/adoi/Libnr)
* [Ngxs-Pizza-Order](https://github.com/tommythongnguyen/Ngxs-Pizza-Order)
* [Ngxs Todo](https://github.com/mailok/todo-ngxs)
* [EL-3270 Electron IBM Terminal Emulator](https://github.com/mflorence99/el-3270)
* [*El terminador* Electron-based Terminal Manager, inspired by iTerm2](https://github.com/mflorence99/el-term)
* [*Elf* Electron-based File Manager, with state from selection to file system completely managed by NGXS](https://github.com/mflorence99/el-file)
* [Angular NGXS Tutorial - An Alternative to NgRx for State Management](https://coursetro.com/posts/code/152/Angular-NGXS-Tutorial---An-Alternative-to-Ngrx-for-State-Management)
* [NGXS + Firebase Demo](https://github.com/fisenkodv/itinerary)
* [Use NGXS in a shared module](https://stackblitz.com/edit/angular-shared-for-root-imports?file=app%2Fshared-components%2Fshared-components.module.ts)
* [ScuttleButt Client using NGXS](https://github.com/datenknoten/ngx-ssb-client)
* [Movies Catalog APP (mobile & desktop) with NGXS, Angular 6, Ionic 4 and Capacitor](https://github.com/abritopach/angular-ionic-ngxs-movies)
* [NGXS Form Example](https://github.com/kuncevic/ngxs-form-example)
* [ngxs coffee](https://github.com/chybie/ngxs-coffee)
* [ngxs vs NgRx](https://github.com/codediodeio/ngrx-vs-ngxs)
* [Ngxs Effects](https://github.com/hsdgit/State.Of.Angular/tree/effects)
* [Reactive Programming with Observables & NGXS](https://github.com/kctang/reactive-with-ngxs)
* [Port of NgRx Example App](https://github.com/eranshmil/ngxs-example-app)
* [State Management with NGXS](https://github.com/joaqcid/state-mgmt-with-ngxs)
* [Fretboard Learning (Game/tool built using angular, Ionic and NGXS)](https://guitar-fretboard-learning.web.app/)
* [Arkham Horror Card Game (Built using Angular and NGXS)](https://github.com/sandb0x4477/arkham-horror-lcg)

### Media

* [ngAtlanta - NGXS, State Management Made Simple - Jecelyn Yeen](https://youtu.be/0bhfUGjn0KA)
* [ngAir 153 - NGXS: A New State Management for Angular Apps with Austin McDaniel and Danny Blue](https://www.youtube.com/watch?v=rkn73khwfWU\&feature=youtu.be)
* [ngAir 196 - One year of NGXS with Mark Whitfeld](https://youtu.be/B7m7eWywJB0)
* [Quick Start to NGXS](https://youtu.be/SGj11j4hxmg)
* [NGXS: Redux implemented in 2018 by Gerard Sans](https://youtu.be/nh-mp85folo?t=3240)
* [Angular NGXS Tutorial - An Alternative to NgRx for State Management](https://youtu.be/SfiO3bDUK7Q)

### Articles

* [@amcdnl - Authentication in NGXS](https://medium.com/@amcdnl/authentication-in-ngxs-6f25c52fd385)
* [@amcdnl - Why another state management framework for Angular?](https://medium.com/@amcdnl/why-another-state-management-framework-for-angular-b4b4c19ef664)
* [Alligator - Manage State in Angular with NGXS](https://alligator.io/angular/ngxs/)
* [@joshblf - Migrating from NGRX to NGXS in Angular 6](https://medium.com/@joshblf/migrating-from-ngrx-to-ngxs-in-angular-6-ddddcdce543e)
* [< BE OUTSTANDING /> - Why I Prefer NGXS over NGRX](https://blog.singular.uk/why-i-prefer-ngxs-over-ngrx-df727cd868b5)
* [JWORKS TECH BLOG - NGRX VS. NGXS VS. AKITA VS. RXJS: FIGHT!](https://ordina-jworks.github.io/angular/2018/10/08/angular-state-management-comparison.html)
* [The InfoGrid - Angular – Managing Authentication State Using NGXS](https://theinfogrid.com/tech/developers/angular/ngxs-authentication-angular/)
* [C# Corner - Angular With NGXS - State Management](https://www.c-sharpcorner.com/blogs/angular-with-ngxs-statemanagement)
* [@timdeschryver - Simple state mutations in NGXS with Immer](https://blog.angularindepth.com/simple-state-mutations-in-ngxs-with-immer-48b908874a5e)
* [@mehmetakifalp - Keeping Multiple Tab In Sync using NGXS state management library, Rxjs and localStorage](https://medium.com/@mehmetakifalp/keeping-multiple-tab-in-sync-using-ngxs-state-management-library-rxjs-and-localstorage-840c0bf615fa)
* [Q Software - NGXS — Initial impressions of an Angular state management solution](https://medium.com/q-software/ngxs-initial-impressions-of-an-angular-state-management-solution-a44b59f52508)
* [Bratislava Angular - Ngxs and Firebase Authentication](https://medium.com/bratislava-angular/ngxs-and-firebase-authentication-2c2a1c1196d6)
* [@hi\_46634 - Angular NGXS and WebSockets with Laravel backend](https://medium.com/@hi_46634/angular-ngxs-and-websockets-with-laravel-backend-2e66e0183cc2)
* [@dazcyril - State Management in Angular](https://medium.com/@dazcyril/state-management-in-angular-9ebae914ca9a)
* HSD - State Management In Angular using NGXS - [Part1](https://www.hsd.com.au/blog/state-management-in-angular-using-ngxs-part-1/), [Part2](https://www.hsd.com.au/blog/state-management-in-angular-using-ngxs-part-2/)
* [App Dividend - Angular NGXS Tutorial With Example From Scratch](https://appdividend.com/2018/07/03/angular-ngxs-tutorial-with-example-from-scratch/)
* [Angular Firebase - NGXS Quick Start Tutorial](https://angularfirebase.com/lessons/ngxs-quick-start-angular-state-management)
* [coursetro - Angular NGXS Tutorial - An Alternative to Ngrx for State Management](https://coursetro.com/posts/code/152/Angular-NGXS-Tutorial---An-Alternative-to-Ngrx-for-State-Management)
* [@splincode - NGXS Facade](https://medium.com/ngxs/ngxs-facade-3aa90c41497b)
* [@alvino.aj - NGXS — Thoughts, Patterns, Architecture and best practices](https://medium.com/@alvino.aj/ngxs-thoughts-patterns-architecture-and-best-practices-c991c42618d9)
* [Angular Chile - Manejo de Estado con NGXS en Angular (Spanish)](https://medium.com/angular-chile/manejo-de-estado-con-ngxs-en-angular-e66e11198a0)

If you have content you'd like to share with the community, make a PR to add it here.


# Developer Guide

Welcome to the NGXS community! We're excited to have you here. This guide will help you set up your local development environment and contribute effectively. :rocket:

## Prerequisites

Before you begin, ensure you have met the following requirements:

* You have installed [**Node.js**](https://nodejs.org/)
* You have installed [**Yarn**](https://yarnpkg.com/)

## Installation

Follow these steps to set up your local environment:

1. Fork the repository if you haven't already. [Learn how](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo).
2. Clone the forked repository to your local machine using git.
3. Install project dependencies:

   ```bash
   # Install root dependencies
   yarn install

   # Install dependencies for the "create-app" tutorial
   yarn --cwd tutorials/create-app
   ```
4. Build all packages:

   ```bash
   yarn build:packages
   ```

## Developing and Contributing

If you want to contribute to the project by fixing bugs, adding new features, or creating new packages, follow the steps below.

### Modifying `@ngxs/store`

1. Run development mode:

   ```bash
   yarn build:packages --package store --watch
   ```
2. Run serve integration examples:

   ```bash
   yarn start
   ```
3. **Make your changes...**
4. Run tests to ensure everything works correctly:

   ```bash
   yarn test
   ```
5. Commit changes following the [Conventional Commits](https://www.conventionalcommits.org/) format.
6. Create a **pull request** with a detailed description of the changes.

### Adding a New Package: `@ngxs/<my-super-plugin>`

1. Create a new package directory `packages/<my-super-plugin>`.
2. Create a template library with `ngPackagr`.
3. Add the package to `package.json` at the root level.
4. Run development mode:

   ```bash
   yarn build:packages --package <my-super-plugin> --watch
   ```
5. **Develop your plugin...**
6. Build the package:

   ```bash
   yarn build:packages --package <my-super-plugin>
   ```
7. Run tests to ensure everything works correctly:

   ```bash
   yarn test
   ```
8. Commit changes following the [Conventional Commits](https://www.conventionalcommits.org/) format.
9. Create a **pull request** with a detailed description of the changes.


# Contributors

Thanks to all our [contributors](https://github.com/ngxs/store/graphs/contributors)!

![](https://opencollective.com/ngxs/contributors.svg?width=890)


# Contributing

We would love for you to contribute to our project and help make it ever better! As a contributor, here are the guidelines we would like you to follow.

* [Report Issues](#report-issues)
* [Request Features](#request-features)
* [Submitting a Pull Request (PR)](#submitting-a-pull-request-pr)
* [Commit Message Format](#commit-message-format)

## Report Issues

If you find a bug in the source code or a mistake in the documentation, you can help us by submitting an issue to our GitHub Repository. Including an issue reproduction (via Stackblitz, Plunkr, etc.) is the absolute best way to help the team quickly diagnose the problem. Screenshots are also helpful.

You can help the team even more and submit a Pull Request with a fix.

## Issue Etiquette

Before you submit an issue, search the archive, maybe your question was already answered.

If your issue appears to be a bug, and hasn't been reported, open a new issue. Help us to maximize the effort we can spend fixing issues and adding new features by not reporting duplicate issues. Providing the following information will increase the chances of your issue being dealt with quickly:

* Overview of the Issue - if an error is being thrown a non-minified stack trace helps
* Angular and ngxs Versions - which versions of Angular and ngxs are affected
* Motivation for or Use Case - explain what are you trying to do and why the current behavior is a bug for you
* Browsers and Operating System - is this a problem with all browsers?
* Reproduce the Error - provide a live example (using Stackblitz, Plunker, etc.) or a unambiguous set of steps
* Screenshots - Due to the visual nature of ngxs, screenshots can help the team triage issues far more quickly than a text description.
* Related Issues - has a similar issue been reported before?
* Suggest a Fix - if you can't fix the bug yourself, perhaps you can point to what might be causing the problem (line of code or commit)

## Request Features

You can request a new feature by submitting an issue to our GitHub Repository. If you would like to implement a new feature, please submit an issue with a proposal for your work first, to be sure that we can use it. Please consider what kind of change it is:

* For a Major Feature, first open an issue and outline your proposal so that it can be discussed. This will also allow us to better coordinate our efforts, prevent duplication of work, and help you to craft the change so that it is successfully accepted into the project.
* Small Features can be crafted and directly submitted as a Pull Request.

## Submitting a Pull Request (PR)

Before you submit a Pull Request (PR) consider the following guidelines:

* Search [GitHub](https://github.com/amcdnl/ngxs/pulls) for an open or closed PR that relates to your submission. You don't want to duplicate effort.
* Create a new git branch:

  ```shell
  git checkout -b my-fix-branch master
  ```
* Make changes on your local branch.
* Run the full test suite and ensure that all tests pass.
* Commit your changes using a descriptive commit message that follows our [commit message guidelines](#commit-message-guidelines). Adherence to these conventions is necessary to keep a clean git log.
* Push your branch to GitHub:

  ```shell
  git push origin my-fix-branch
  ```
* In GitHub, send a pull request to `ngxs:master`.
* If we suggest changes then:
  * Make the required updates.
  * Re-run the test suites to ensure tests are still passing.
  * Rebase your branch and force push to your GitHub repository (this will update your Pull Request):

    ```shell
    git rebase master -i
    git push -f
    ```

That's it! Thank you for your contribution!

## Commit Message Format

Each commit message consists of a **header**, a **body** and a **footer**. The header has a special format that includes a **type**, a **scope** and a **subject**:

```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```

The **header** is mandatory and the **scope** of the header is optional.

Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier to read on GitHub as well as in various git tools.

### Revert

If the commit reverts a previous commit, it should begin with `revert:`, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.

### Type

Must be one of the following:

* **feat**: A new feature
* **fix**: A bug fix
* **docs**: Documentation only changes
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **perf**: A code change that improves performance
* **test**: Adding missing tests
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation generation

### Scope

The scope could be anything specifying place of the commit change. For example `Store`, `Mutation`, `Action`, `Select` etc.

### Subject

The subject contains succinct description of the change:

* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize first letter
* no dot (.) at the end

### Body

Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes". The body should include the motivation for the change and contrast this with previous behavior.

### Footer

The footer should contain any information about **Breaking Changes** and is also the place to reference GitHub issues that this commit **Closes**.

**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.


# Sponsors

## Sponsors

Support this project by becoming a sponsor. Your logo will show up here with a link to your website. [Become a sponsor](https://opencollective.com/ngxs#sponsor)

[![Primary](https://opencollective.com/ngxs/sponsor/0/avatar.svg)](https://opencollective.com/ngxs/sponsor/0/website) [![Sponsor 1](https://opencollective.com/ngxs/sponsor/1/avatar.svg)](https://opencollective.com/ngxs/sponsor/1/website) [![Sponsor 2](https://opencollective.com/ngxs/sponsor/2/avatar.svg)](https://opencollective.com/ngxs/sponsor/2/website) [![Sponsor 3](https://opencollective.com/ngxs/sponsor/3/avatar.svg)](https://opencollective.com/ngxs/sponsor/3/website) [![Sponsor 4](https://opencollective.com/ngxs/sponsor/4/avatar.svg)](https://opencollective.com/ngxs/sponsor/4/website) [![Sponsor 5](https://opencollective.com/ngxs/sponsor/5/avatar.svg)](https://opencollective.com/ngxs/sponsor/5/website) [![Sponsor 6](https://opencollective.com/ngxs/sponsor/6/avatar.svg)](https://opencollective.com/ngxs/sponsor/6/website) [![Sponsor 7](https://opencollective.com/ngxs/sponsor/7/avatar.svg)](https://opencollective.com/ngxs/sponsor/7/website) [![Sponsor 8](https://opencollective.com/ngxs/sponsor/8/avatar.svg)](https://opencollective.com/ngxs/sponsor/8/website) [![Sponsor 9](https://opencollective.com/ngxs/sponsor/9/avatar.svg)](https://opencollective.com/ngxs/sponsor/9/website)

## Backers

Thank you to all our backers! [Become a backer](https://opencollective.com/ngxs#backer) [![Backers](https://opencollective.com/ngxs/backers.svg?width=890)](https://opencollective.com/ngxs#backers)

## Other Contributions

* [DataFrameworks](https://dataframeworks.com/) - WebSocket Plugin
* [Marian Stoica](https://twitter.com/MarianStoica19) - NGXS.io domain name


# NGXS LABS

<div align="center"><img src="/files/-LVo51Ewbu7a_GyYrF6L" alt=""></div>

We announced a new idea called [NGXS Labs](https://github.com/ngxs-labs). The goal of NGXS Labs is to more clearly communicate the balance between new explorations by the team, with the normal stability that our community has come to expect since the release of NGXS.

#### Introduction

There is definitely no lack of enthusiasm for the NGXS project and as a result there has been a proliferation of pull requests to add new features to the framework. This is very exciting but at the same time has been one of the big challenges. How do we incorporate the growing innovation around the framework and experiment with different ideas without compromising the stability and comprehensibility of the core framework? In response to this we have created NGXS Labs.

The idea with this github organisation is to provide a place for the community to create libraries that augment the main framework with functionality that does not need to be integrated directly into the framework and therefore can evolve through their initial iterations of experimentation without affecting the main `@ngxs/store` library. Once a project in the labs space has stabilised, has received significant adoption and is accepted as a recommended approach then it can be moved to the ngxs github organisation.

From time to time we will be posting about projects that have been started under the ngxs-labs organisation to get community involvement and feedback around them.

#### Labs Packages

| Package                                                                                      | Version                                                                                                               | Status      |
| -------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | ----------- |
| [@anglar-ru/ngxs](https://angular-ru.gitbook.io/sdk/ngxs/ngxs)                               | [![latest](https://img.shields.io/npm/v/%40angular-ru%2Fngxs/latest.svg)](https://npmjs.com/package/@angular-ru/ngxs) | Stable      |
| [@ngxs-labs/emitter](https://npmjs.com/package/@ngxs-labs/emitter)                           | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Femitter/latest.svg)                                                   | Stable      |
| [@ngxs-labs/immer-adapter](https://npmjs.com/package/@ngxs-labs/immer-adapter)               | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Fimmer-adapter/latest.svg)                                             | Stable      |
| [@ngxs-labs/dispatch-decorator](https://npmjs.com/package/@ngxs-labs/dispatch-decorator)     | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Fdispatch-decorator/latest.svg)                                        | Stable      |
| [@ngxs-labs/select-snapshot](https://npmjs.com/package/@ngxs-labs/select-snapshot)           | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Fselect-snapshot/latest.svg)                                           | Stable      |
| [@ngxs-labs/async-storage-plugin](https://npmjs.com/package/@ngxs-labs/async-storage-plugin) | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Fasync-storage-plugin/latest.svg)                                      | Alpha       |
| [@ngxs-labs/entity-state](https://npmjs.com/package/@ngxs-labs/entity-state)                 | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Fentity-state/latest.svg)                                              | Development |
| [@ngxs-labs/actions-executing](https://npmjs.com/package/@ngxs-labs/actions-executing)       | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Factions-executing/latest.svg)                                         | Alpha       |
| [@ngxs-labs/attach-action](https://npmjs.com/package/@ngxs-labs/attach-action)               | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Fattach-action/latest.svg)                                             | Alpha       |
| [@ngxs-labs/firestore-plugin](https://npmjs.com/package/@ngxs-labs/firestore-plugin)         | ![](https://img.shields.io/npm/v/%40ngxs-labs%2Ffirestore-plugin/latest.svg)                                          | Alpha       |


# DEPRECATIONS


# Inject Container State Deprecation

The `injectContainerState` feature is scheduled for removal in future updates. Instead, it can now be declared in the global configuration when invoking `forRoot` or `provideStore`, or through the `@SelectorOptions` decorator. This property was introduced several years ago to facilitate the incremental migration of existing codebases.

This change specifically impacts the runtime behavior of the `@Selector` decorator and how parameters are passed into selector functions, especially when `@Selector` is used with joined selectors. It's important to note that this change does not affect the behavior of `createSelector`.

No changes need to be made when `@Selector` is called with no arguments within the state class:

```ts
export class InvoiceState {
  @Selector()
  static getInvoiceId(state: InvoiceStateModel) {
    return state.id;
  }
}
```

However, if you're calling the decorator with arguments, you would expect the container state to be injected as the first argument:

```ts
export class InvoiceLinesState {
  @Selector([InvoiceState.getInvoiceId])
  static getInvoiceLinesByInvoiceId(state: InvoiceLinesStateModel, invoiceId: number) {
    return state.invoiceLines.filter(line => line.invoiceId === invoiceId);
  }
}
```

With `injectContainerState` being removed and set to `false` by default, you now need to explicitly specify the container state in the above example:

```ts
export class InvoiceLinesState {
  @Selector()
  static getInvoiceLines(state: InvoiceLinesStateModel) {
    return state.invoiceLines;
  }

  @Selector([InvoiceLinesState.getInvoiceLines, InvoiceState.getInvoiceId])
  static getInvoiceLinesByInvoiceId(invoiceLines: InvoiceLine[], invoiceId: number) {
    return invoiceLines.filter(line => line.invoiceId === invoiceId);
  }
}
```


# Sub States Deprecation

We're planning to remove the option to declare sub-states on the state using the `children` property. This feature was introduced years ago to address certain issues, but it's not technically beneficial and doesn't add any value.

Moreover, this feature has been restrictive because you always had to consider state erasure when calling `ctx.setState` in states that have sub-states. This is because `ctx.setState` removes the sub-state, which is mostly invisible from the parent state.

Therefore, it necessitated maintaining a relationship between a parent and a child state.

It's preferable to have separate states that maintain the relationship. There shouldn't be bidirectional dependencies between states, as it often leads to cyclic dependency errors.

For example, if you have an invoice state and an invoice lines state, instead of tying the invoice lines state to the invoice state through `children: [InvoiceLinesState]`, you can keep `InvoiceLinesState` entirely separate. Each invoice line item may have an `invoiceId` property. Then, when you want to select a list of line items for an invoice, you can join the line items state selector with `InvoiceState.getInvoiceId` or something similar to retrieve the invoice ID, and then filter the invoice lines list by `invoiceId`.


# Select Decorator Deprecation

The `@Select` decorator is slated for removal in the future due to its inherent risks. It lacks integration with Angular's dependency injection system, making it prone to failures in scenarios with multiple simultaneous applications, such as server-side rendering and microfrontend setups.

Previously, the decorator stored the `Store` instance in a static variable, which could be overwritten by subsequent bootstrapped or removed applications. If a second application was created and destroyed before the first one, it could nullify the static variable, rendering the store inaccessible to the first application.

Every `@Select` usage should be replaced with the following:

```ts
class UsersComponent {
  @Select(UsersState.getUsers) users$!: Observable<User[]>;

  // Should become the following
  users$: Observable<User[]> = inject(Store).select(UsersState.getUsers);
}
```

The `store.select` method now requires a typed selector to be provided. Therefore, if the `@Select` decorator previously accepted a string or an anonymous function, it should be replaced with a selector:

```ts
class UsersComponent {
  @Select('users') users$!: Observable<User[]>;
  // Or
  @Select(state => state.users) users$!: Observable<User[]>;

  // Should become the following
  users$: Observable<User[]> = inject(Store).select(UsersState.getUsers);
}
```

We could potentially provide a schematic migration that simply replaces the code. However, since the select decorator was permitted to be used inside classes not created by Angular dependency injection, our code replacement approach could still be flawed.


# NGXS

<div align="left"><figure><picture><source srcset="/files/X5Z8txIaGorWpV67U9Ko" media="(prefers-color-scheme: dark)"><img src="/files/4AydZ0JS6OyWSgnobHbW" alt="" width="250"></picture><figcaption></figcaption></figure></div>

[![Discord](https://img.shields.io/discord/1008573955587702894?style=flat-square\&logo=discord\&label=discord\&link=https%3A%2F%2Fdiscord.com%2Fchannels%2F1008573955587702894)](https://discord.com/channels/1008573955587702894) [![](https://badge.fury.io/js/%40ngxs%2Fstore.svg)](https://badge.fury.io/js/%40ngxs%2Fstore) [![](https://api.codeclimate.com/v1/badges/5b43106a1ddff7d76a04/maintainability)](https://codeclimate.com/github/ngxs/store/maintainability) [![](https://api.codeclimate.com/v1/badges/5b43106a1ddff7d76a04/test_coverage)](https://codeclimate.com/github/ngxs/store/test_coverage) [![](https://circleci.com/gh/ngxs/store/tree/master.svg?style=svg)](https://circleci.com/gh/ngxs/store)

### ❓ What is NGXS?

NGXS is a state management pattern + library for Angular. It acts as a single source of truth for your application's state, providing simple rules for predictable state mutations.

NGXS is modeled after the CQRS pattern popularly implemented in libraries like Redux and NgRx but reduces boilerplate by using modern TypeScript features such as classes and decorators.

### 👋 New to NGXS?

If you're just getting started with NGXS, I recommend you head over to the [concepts](/master/readme/intro) and then explore the rich ecosystem of examples in the [community resources](/master/community-and-labs/community/projects) page.

### ❓ Need Help?

For questions, please ask them on Stack Overflow with the `ngxs` tag: <https://stackoverflow.com/questions/ask?tags=ngxs>

To chat with other users and contributors join us on Discord: <https://discord.gg/yT3Q8cXTnz> (PS. we are migrating from our [Slack](https://join.slack.com/t/ngxs/shared_invite/zt-by26i24h-2CC5~vqwNCiZa~RRibh60Q) server)

If you think there is a bug in this library, you can open an issue on GitHub (<https://github.com/ngxs/store/issues/new>). If possible a link to a [http://stackblitz.com](https://stackblitz.com/edit/ngxs-repro) (or github) repo with a repro or a failing test would be great.

### ❤️ Giving Back

Become a [Contributor](/master/community-and-labs/community/contributors) or a [Sponsor](/master/community-and-labs/community/sponsors).

## Sponsors

Thank you to the organisations sponsoring us and to the individuals that financially back our work and the running of our open source community. Become [a sponsor](https://opencollective.com/ngxs#sponsor) or [a backer](https://opencollective.com/ngxs#backer) today. Every bit helps!

### Organisations

[![Organisations](https://opencollective.com/ngxs/sponsors.svg?width=890\&avatarHeight=100)](https://opencollective.com/ngxs#sponsors)

### Individuals

[![Backers](https://opencollective.com/ngxs/backers.svg?width=890)](https://opencollective.com/ngxs#backers)

## Contributors

Thanks to all our [contributors](https://github.com/ngxs/store/graphs/contributors)! Open source does not work without you!

![](https://opencollective.com/ngxs/contributors.svg?width=890)


# Overview

There are 4 major concepts to NGXS:

* Store: Global state container, action dispatcher and selector
* Actions: Class describing the action to take and its associated metadata
* State: Class definition of the state
* Selects: State slice selectors

These concepts create a circular control flow traveling from a component dispatching an action, to a store reacting to the action, back to the component through a state select.

![](/files/-LZoLea7ZgBJTqq73TVX)


# WHY

Why another state management solution? We asked ourselves that same question before we started on NGXS. After trial and error of several different redux based solutions we decided that they didn’t represent the type of API we wanted and expected from Angular.

### Simple

NGXS tries to make things as simple and accessible as possible. There can be a lot of boilerplate code in state management, thus a main goal of NGXS is to reduce boilerplate allowing you to do more things with less. It is also not necessary to be super familiar with RxJs.

RxJs is great and is made use of heavily internally within the project, but the library tries to do as much for you as it can. NGXS drives to let users take advantage of the benefits of Observables but in many cases treat them as an implementation detail of the library rather than a prerequisite.

The other thing that NGXS gets rid of is switch statements. The library is responsible for knowing when functions need to be called.

### Dependency Injection (DI)

A core feature of Angular is dependency injection. It can be a very useful tool and NGXS makes sure that users can use DI in their state management code. This means Angular services can be injected into state classes making it easier to take advantage of more Angular features.

### Action Life Cycles

Actions in NGXS are asynchronous. This allows actions to have a life cycle, meaning we can now listen for when a single action or a collection of actions is complete making complex workflows predictable. It is very common to want to do something after an action is completed and NGXS makes it simple to do.

### Promises

Observables are great but they aren't a silver bullet. Sometimes Promises are the preferred option. NGXS allows either to be returned from an action method.

### Community

NGXS is entirely community built and driven. The project exists to help people build applications and the team is open to any suggestions that help with that goal.


# INSTALLATION

## Installing with schematics

You can install the `@ngxs/store` using `ng-add` schematic

```bash
ng add @ngxs/store
```

Note: This command will prompt you to choose the **plugins** you want to install and the name of the **project** you want to use NGXS with.

You have the option to enter the options yourself

```bash
ng add @ngxs/store --plugins DEVTOOLS,FORM --project angular-ngxs-project
```

| Option    | Description                                               | Default Value               |
| --------- | --------------------------------------------------------- | --------------------------- |
| --project | Name of the project as it is defined in your angular.json | Workspace's default project |
| --plugins | Comma separate the plugins as appear below                |                             |

### Plugins to optionally install using the schematics

* Ngxs developer tools plugin
* Ngxs form plugin
* Ngxs HMR plugin
* Ngxs logger plugin
* Ngxs router plugin
* Ngxs storage plugin
* Ngxs websocket plugin

You can find more information about plugins on the [plugins page](https://www.ngxs.io/plugins).

🪄 **This command will**:

* Update `package.json` dependencies with `@ngxs/store`
* Update `package.json` dependencies with the selected plugins
* Install dependencies by executing `npm install`

If your project is standalone one:

* Update the `providers` array of your selected project with `provideStore([])`

If your application is module based:

* Update the `imports` array of your `app.module.ts` with `NgxsModule.forRoot([])`

## Manual Installation

To get started, install the package from npm. The latest version (3.x) supports Angular/RxJS 6+.

```bash
npm i @ngxs/store

# or if you are using yarn
yarn add @ngxs/store

# or if you are using pnpm
pnpm i @ngxs/store
```

Then, in your `app.config.ts`, add the `provideStore` to the list of providers:

```ts
import { provideStore } from '@ngxs/store';

export const appConfig: ApplicationConfig = {
  providers: [provideStore()]
};
```

When you provide the store at the root level, you can pass root states along with [options](/master/concepts/store/options). If you are lazy loading, you can use the `provideStates` option with the same arguments.

Options such as `developmentMode` can be passed to the module as the second argument in the `provideStore` function. In development mode, plugin authors can add additional runtime checks/etc to enhance the developer experience. Switching to development mode will also freeze your store using [deep-freeze-strict](https://www.npmjs.com/package/deep-freeze-strict) module.

It's important that you add `provideStore` at the root level even if all of your states are feature states.

## Development Builds

Our continuous integration server runs all tests on every commit to master and if they pass it will publish a new development build to NPM and tag it with the @dev tag.

This means that if you want the bleeding edge of `@ngxs/store` or any of the plugins you can simply do:

```bash
npm install @ngxs/store@dev
npm install @ngxs/logger-plugin@dev
npm install @ngxs/devtools-plugin@dev

# or if you are using yarn
yarn add @ngxs/store@dev
yarn add @ngxs/logger-plugin@dev
yarn add @ngxs/devtools-plugin@dev

# of if you want to update multiple things at the same time
yarn add @ngxs/{store,logger-plugin,devtools-plugin}@dev

# or if you are using pnpm
pnpm install @ngxs/store@dev
pnpm install @ngxs/logger-plugin@dev
pnpm install @ngxs/devtools-plugin@dev
```

This will install the version currently tagged as `@dev`. Your package.json file will be locked to that specific version.

```json
{
  "dependencies": {
    "@ngxs/store": "3.0.0-dev.a0d076d"
  }
}
```

If you later want to again update to the bleeding edge, you will have to run the above command again.


# STARTER KIT

The Starter Kit provides a pre-configured NGXS setup that includes a Store, State, Actions, and selectors.

## Installing with schematics

```bash
ng generate @ngxs/store:starter-kit
```

Note: Running this command will prompt you to create a "Starter-Kit". The options available for the "Starter-Kit" are listed in the table below.

You have the option to enter the options yourself

```bash
ng generate @ngxs/store:starter-kit --path YOUR_PATH
```

| Option    | Description                                                    | Required | Default Value               |
| --------- | -------------------------------------------------------------- | :------: | --------------------------- |
| --path    | The path to create the starter kit                             |    Yes   |                             |
| --spec    | Boolean flag to indicate if a unit test file should be created |    No    | `true`                      |
| --project | Name of the project as it is defined in your angular.json      |    No    | Workspace's default project |

> When working with multiple projects within a workspace, you can explicitly specify the `project` where you want to install the **starter kit**. The schematic will automatically detect whether the provided project is a standalone or not, and it will generate the necessary files accordingly.

🪄 **This command will**:

* Create Auth State, Actions, Selectors and Unit Tests, organized into an 'auth' directory
* Create Dictionary State, Actions, Selectors and Unit Tests, organized into a 'dashboard/states/dictionary' directory
* Create User State, Actions, Selectors and Unit Tests, organized into a 'dashboard/states/user' directory
* Create a Store and Configure the Auth, Dictionary and User states

> Note: The generated files will be organized into a 'store' directory.


# SCHEMATICS

This page lists all the different schematics that can be used to generate NGXS Starter-Kit, Store, Actions and State.

## Starter Kit

The Starter Kit provides a pre-configured NGXS setup that includes a Store, State, Actions, and selectors.

See the [Starter Kit Page](/master/introduction/starter-kit) to learn more.

## Store

The store is a global state manager that dispatches actions your state containers listen to and provides a way to select data slices out from the global state.

See the [Store Schematics Page](/master/concepts/store/schematics) to learn more.

## Actions

Actions can either be thought of as a command which should trigger something to happen, or as the resulting event of something that has already happened.

See the [Action Schematics Page](/master/concepts/actions/schematics) to learn more.

## State

States are classes that define a state container.

See the [State Schematics Page](/master/concepts/state/schematics) to learn more.


# STORE

The store is a global state manager that dispatches actions your state containers listen to and provides a way to select data slices out from the global state.

### Creating actions

An action example in `animal.actions.ts`.

```ts
export class AddAnimal {
  static readonly type = '[Zoo] Add Animal';

  constructor(public name: string) {}
}
```

### Dispatching actions

To dispatch actions, you need to inject the `Store` service into your component/service and invoke the `dispatch` function with an action or an array of actions you wish to trigger.

```ts
import { Store } from '@ngxs/store';
import { AddAnimal } from './animal.actions';

@Component({ ... })
export class ZooComponent {
  constructor(private store: Store) {}

  addAnimal(name: string) {
    this.store.dispatch(new AddAnimal(name));
  }
}
```

You can also dispatch multiple actions at the same time by passing an array of actions like:

```ts
this.store.dispatch([new AddAnimal('Panda'), new AddAnimal('Zebra')]);
```

Let's say after the action executes you want to clear the form. Our `dispatch` function actually returns an Observable, so we can subscribe to it and reset the form after it was successful.

```ts
import { Store } from '@ngxs/store';
import { AddAnimal } from './animal.actions';

@Component({ ... })
export class ZooComponent {
  constructor(private store: Store) {}

  addAnimal(name: string) {
    this.store.dispatch(new AddAnimal(name)).subscribe(() => this.form.reset());
  }
}
```

The Observable that a dispatch returns has a void type, this is because there can be multiple states that listen to the same `@Action`, therefore it's not realistically possible to return the state from these actions since we don't know the form of them.

If you need to get the state after this, simply use `selectSignal` in the chain like:

```ts
import { Store } from '@ngxs/store';
import { Observable } from 'rxjs';
import { withLatestFrom } from 'rxjs';

import { AnimalState } from './animal.state';
import { AddAnimal } from './animal.actions';

@Component({ ... })
export class ZooComponent {
  animals = this.store.selectSignal(AnimalState.getAnimals);

  constructor(private store: Store) {}

  addAnimal(name: string) {
    this.store.dispatch(new AddAnimal(name)).subscribe(() => {
      console.log(this.animals());
      // do something with animals
      this.form.reset();
    });
  }
}
```

#### `dispatch` Utility

NGXS offers a utility function named `dispatch`, which takes an action as a parameter and returns a function. This function can then be called with parameters for the action constructor. When this function is called, the action is created and is dispatched immediately:

```ts
import { dispatch } from '@ngxs/store';

// An action declared somewhere in your app
class Greet {
  static readonly type = 'Greet';

  constructor(public greeting: string) {}
}

// Then, in your component
export class MyComponent {
  greet = dispatch(Greet);

  constructor() {
    // the `this.greet` function has the same signature as the action's constructor!
    this.greet('Hello world!');
  }
}
```

The dispatched function returns a value that is both an `Observable` and a `PromiseLike`, so you can use either reactive or async/await patterns without any API change — the syntax at the call site determines the behavior.

**Reactive (subscribe):**

```ts
export class MyComponent {
  greet = dispatch(Greet);

  onGreet() {
    this.greet('Hello world!').subscribe(() => {
      // action completed
    });
  }
}
```

**Async/await:**

```ts
export class MyComponent {
  greet = dispatch(Greet);

  async onGreet() {
    await this.greet('Hello world!');
    // action completed
  }
}
```

**Error handling with async/await:**

If the action throws, the rejection is propagated into the promise so a standard `try/catch` works as expected:

```ts
export class MyComponent {
  greet = dispatch(Greet);

  async onGreet() {
    try {
      await this.greet('Hello world!');
    } catch (err) {
      // handle error
    }
  }
}
```

### Snapshots

You can get a snapshot of the state by calling `store.snapshot()`. This will return the entire value of the store for that point in time.

### Selecting State

See the [select](/master/concepts/select) page for details on how to use the store to select data.

### Reset

In certain situations you need the ability to reset the state in its entirety without triggering any actions or life-cycle hooks. One example of this would be redux devtools plugin when we are doing time travel. Another example would be when we are unit testing and need the state to be a specific value for isolated testing.

`store.reset(myNewStateObject)` will reset the entire state to the passed argument without firing any actions or life-cycle events.

Warning: Using this can cause unintended side effects if improperly used and should be used with caution!


# Store Schematics

You can generate the `store` using the command as seen below:

```bash
ng generate @ngxs/store:store
```

Running this command will prompt you to create a "Store" with the options as they are listed in the table below.

Alternatively, you can provide the options yourself.

```bash
ng generate @ngxs/store:store --name NAME_OF_YOUR_STORE
```

| Option    | Description                                                    | Required | Default Value               |
| --------- | -------------------------------------------------------------- | :------: | --------------------------- |
| --name    | The name of the store                                          |    Yes   |                             |
| --path    | The path to create the store                                   |    No    | App's root directory        |
| --spec    | Boolean flag to indicate if a unit test file should be created |    No    | `true`                      |
| --flat    | Boolean flag to indicate if a dir is created                   |    No    | `false`                     |
| --project | Name of the project as it is defined in your angular.json      |    No    | Workspace's default project |

> When working with multiple projects within a workspace, you can explicitly specify the `project` where you want to install the **store**. The schematic will automatically detect whether the provided project is a standalone or not, and it will generate the necessary files accordingly.

> Be sure to update `provideStore` in `app.config.ts` if working with standalone project or `NgxsModule.forRoot([])` in `app.module.ts` if working with module based project. Without this, your app will not recognise your store and actions properly.

🪄 **This command will**:

* Generate a `{name}.actions.ts`
* Generate a `{name}.state.spec.ts`
* Generate a `{name}.state.ts`. The state file also includes an action handler for the generated action.

> Note: If the --flat option is false, the generated files will be organized into a directory named using the kebab case of the --name option. For instance, 'MyStore' will be transformed into 'my-store'.


# Store Options

You can provide an `NgxsModuleOptions` object as the second argument of your `NgxsModule.forRoot` call. The following options are available:

* `developmentMode` - Setting this to `true` will add additional debugging features that are useful for development time. This includes freezing your state and actions to guarantee immutability. (Default value is `false`). It makes sense to use it only during development to ensure there're no state mutations. When building for production, the `Object.freeze` will be tree-shaken away.
* `selectorOptions` - A nested options object for providing a global options setting to be used for selectors. This can be overridden at the class or specific selector method level using the `SelectorOptions` decorator. The following options are available:
  * `suppressErrors` - Setting this to `true` will cause any error within a selector to result in the selector returning `undefined`. Setting this to `false` results in these errors propagating through the stack that triggered the evaluation of the selector that caused the error. (Default value is `false`).
  * `injectContainerState` ([TO BE DEPRECATED](/master/deprecations/inject-container-state-deprecation)) - Setting this to `true` will inject the container state model as the first parameter of a selector method (defined within a state class) that joins to other selectors for its parameters. Note: This property should not be explicitly set by anyone using versions of NGXS after v3; it only exists for migrating codebases from v3 to versions after v3. See the deprecation notice for further details.
* `compatibility` - A nested options object that allows for the following compatibility options:
  * `strictContentSecurityPolicy` - Set this to `true` in order to enable support for pages where a Strict Content Security Policy has been enabled. This setting circumvent some optimisations that violate a strict CSP through the use of `new Function(...)`. (Default value is `false`)

`ngxs.config.ts`:

> :warning: If your project lacks environment files, you can generate them using the `ng generate environments` command.

```ts
import { NgxsModuleOptions } from '@ngxs/store';

import { environment } from '../environments/environment';

export const ngxsConfig: NgxsModuleOptions = {
  developmentMode: !environment.production,
  selectorOptions: {
    suppressErrors: false
  },
  compatibility: {
    strictContentSecurityPolicy: true
  }
};
```

`app.config.ts`:

```ts
import { provideStore } from '@ngxs/store';

import { ngxsConfig } from './ngxs.config';

export const appConfig: ApplicationConfig = {
  providers: [provideStore(states, ngxsConfig)]
};
```


# Error Handling

## Deterministic vs Non-deterministic

Firstly, it is good to understand that your error handling approach should consider two different classes of error: Deterministic and Non-deterministic errors.

### Deterministic errors:

* These are repeatable errors that you would expect during the normal course of operation of your application.
* The condition for this error to happen is fully determined by the state of the application (hence the word "deterministic").
* `Determinism` is the property that you will always get the same output given the same input.
* If the application's data remains unchanged, then an erroring operation will always fail, no matter how many times it is retried.
* You should consider how your code should handle these errors as part of building a robust application.
* Some example approaches (from the 4xx HTTP status codes):
  * Bad request (400): The data that you are sending is in the incorrect format, something definitely needs to change with what you are sending.
  * Not Found (404): The requested item is not found, so you need to make a decision on how to respond to this scenario.

### Non-deterministic errors:

* These are errors generally occur as a result of the environment within which your application operates. For example, the network or a server failure could cause this type of error.
* Because this type of error lacks `Determinism` (see definition above), then it is possible that retrying the operation could lead to success. It is recommended to decide on a retry strategy that makes sense for the application experience that you wish to offer.
* Some example approaches (from the 5xx HTTP status codes - "server-side" errors ):
  * Internal Server Error (500): Something went wrong with the server. Things could succeed on retry, but it really depends on how resilient your server side is. Not recommended to retry for too long because this type of error could take more than a negligible time to resolve.
  * Gateway Timeout (504): There is a connection timeout, so it may be a good idea to check if there is network availability before retrying too many times.

## Recommended Approach in NGXS

It is recommended to handle errors within your `@Action` function in your state:

### Deterministic errors:

* `Update the state` to capture the error details
  * Ensure that the relevant selectors cater for these error states and provide information for your user to respond to the error accordingly
* OR `dispatch` an action that sends the error details to the necessary state or service
  * This action could be picked up by an application level error state or could be picked up by a service that is listening to the action stream (see [Actions Stream](/master/concepts/actions/actions-stream))

### Non-deterministic errors:

* Respond to the error accordingly(retry, abort, etc.)
* AND use one of the deterministic error handling mechanisms above to inform your user about the situation

## Fallback Error Handling

NGXS has a robost and predictable fallback mechanism for error handling. Although it is not recommended, some developers use these to tailor their application design to suit their team's preference.

Error handling firstly falls back to any error handler at the `dispatch` call and then to the `NgxsUnhandledErrorHandler`.

### Handling at the `dispatch` call

To manually catch an error thrown and not handled by an action, you can subscribe to the observable returned by the `dispatch` call and include an `error` callback. By subscribing and providing an `error` callback, NGXS won't pass the error to its final unhandled error handler.

You can include this error callback in three ways:

* by explicitly supplying the `error` callback in your `subscribe` function call
* by using one of the `rjxs` error handling operators
* by converting the observable into a promise and using any standard `async` or `promise` error handling mechanisms

Check this [special note](#ngxs-error-handling-detection-in-observables) if you have custom code that modifies rxjs's default error fallbacks.

#### Example

Given the following code:

```ts
class AppState {
  @Action(ActionThatCausesAnError)
  unhandledError(ctx: StateContext<StateModel>) {
    // error is thrown
  }
}
```

```ts
import { lastValueFrom } from 'rxjs';

class AppComponent {
  //...
  handleError() {
    this.store.dispatch(new ActionThatCausesAnError()).subscribe({
      error: error => {
        console.log('unhandled error on dispatch subscription: ', error);
      }
    });
  }

  async handleErrorAsync() {
    try {
      await latestValueFrom(this.store.dispatch(new ActionThatCausesAnError()));
    } catch (error) {
      console.log('unhandled error on dispatch caught: ', error);
    }
  }
}
```

You can play around with error handling in the following [stackblitz](https://stackblitz.com/edit/ngxs-error-handling)

### The `NgxsUnhandledErrorHandler`

The final level of fallback in NGXS will pass the error to the `NgxsUnhandledErrorHandler`. The default implementation of this service will pass the error on to the Angular `ErrorHandler` that is configured in the application.

The application developer can choose to provide a custom `NgxsUnhandledErrorHandler` to direct the error as they see fit.

#### Overriding the `NgxsUnhandledErrorHandler`

NGXS provides the `NgxsUnhandledErrorHandler` class, which you can override with your custom implementation to manage unhandled errors according to your requirements:

```ts
import { NgxsUnhandledErrorHandler, NgxsUnhandledErrorContext } from '@ngxs/store';

@Injectable()
export class MyCustomNgxsUnhandledErrorHandler {
  handleError(error: any, unhandledErrorContext: NgxsUnhandledErrorContext): void {
    // Do something with these parameters
  }
}

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: NgxsUnhandledErrorHandler,
      useClass: MyCustomNgxsUnhandledErrorHandler
    }
  ]
};
```

Note that the second parameter, `NgxsUnhandledErrorContext`, contains an object with an `action` property. This property holds the action that triggered the error while being processed.

## Special Notes

### NGXS Error Handling Detection in Observables

In order to acheive the detection of `dispatch` call error handling, NGXS configures the RxJS [`onUnhandledError`](https://rxjs.dev/api/index/interface/GlobalConfig#onUnhandledError) callback. This property is accessible in RxJS versions 7 and above, which is why NGXS mandates a minimum RxJS version of 7.

The RxJS `onUnhandledError` callback triggers whenever an unhandled error occurs within an observable and no `error` callback has been supplied.

:warning: If you configure `onUnhandledError` after NGXS has loaded, you will need to store the existing implementation in a local variable and invoke it when the error is not handled by your customized rxjs error strategy:

```ts
import { config } from 'rxjs';

const existingHandler = config.onUnhandledError;
config.onUnhandledError = function (error: any) {
  if (shouldWeHandleThis(error)) {
    // Do something with this error
  } else {
    existingHandler.call(this, error);
  }
};
```


# Meta Reducers

A meta reducer is a higher order reducer that allows you to take action on the global state rather than a state slice. In NGXS, we don't have this concept but you can accomplish this with [plugins](https://github.com/ngxs/store/blob/master/docs/concepts/store/broken-reference/README.md).

An example of a meta reducer might be to clear the entire state when a user logs out. An example implementation would be:

```ts
import { getActionTypeFromInstance } from '@ngxs/store';

export function logoutPlugin(state, action, next) {
  // Use the get action type helper to determine the type
  if (getActionTypeFromInstance(action) === Logout.type) {
    // if we are a logout type, lets erase all the state
    state = {};
  }

  // return the next function with the empty state
  return next(state, action);
}
```

Then add it to `provideStore` features:

```ts
import { provideStore, withNgxsPlugin } from '@ngxs/store';

export const appConfig: ApplicationConfig = {
  providers: [provideStore([], withNgxsPlugin(logoutPlugin))]
};
```

Now when we dispatch the logout action it will use our new plugin and erase the state.


# ACTIONS

Actions can either be thought of as a command which should trigger something to happen, or as the resulting event of something that has already happened.

Each action contains a `type` field which is its unique identifier.

## Internal Actions

There are two actions that get triggered in the internals of the library:

1. @@INIT - store being initialized, before all the [ngxsOnInit Life-cycle](/master/concepts/state/life-cycle) events.
2. @@UPDATE\_STATE - a new [lazy-loaded state](/master/concepts/state/lazy) being added to the store.

## Simple Action

Let's say we want to update the status of whether the animals have been fed in our Zoo. We would describe a class like:

```ts
export class FeedAnimals {
  static readonly type = '[Zoo] Feed Animals';
}
```

Later in our state class, we will listen to this action and mutate our state, in this case flipping a boolean flag.

## Actions with Metadata

Often you need an action to have some data associated with it. Here we have an action that should trigger feeding a zebra with hay.

```ts
export class FeedZebra {
  static readonly type = '[Zoo] Feed Zebra';

  constructor(
    public name: string,
    public hayAmount: number
  ) {}
}
```

The `name` field of the action class will represent the name of the zebra we should feed. The `hayAmount` tells us how many kilos of hay the zebra should get.

## Dispatching Actions

See [Store](/master/concepts/store) documentation for how to dispatch actions.

## How should you name your actions?

### Commands

Commands are actions that tell your app to do something. They are usually triggered by user events such as clicking on a button, or selecting something.

Names should contain three parts:

* A context as to where the command came from, `[User API]`, `[Product Page]`, `[Dashboard Page]`.
* A verb describing what we want to do with the entity.
* The entity we are acting upon, `User`, `Card`, `Project`.

Examples:

* `[User API] GetUser`
* `[Product Page] AddItemToCart`
* `[Dashboard Page] ArchiveProject`

### Event examples

Events are actions that have already happened and we now need to react to them.

The same naming conventions apply as commands, but they should always be in the past tense.

By using `API` in the context part of the action name we know that this event was fired because of an async action to an API.

Actions are normally dispatched from container components such as router pages. By having explicit actions for each page, it's also easier to track where an event came from.

Examples:

* \[User API] GetUserSuccess
* \[Project API] ProjectUpdateFailed
* \[User Details Page] PasswordChanged
* \[Project Stars Component] StarsUpdated

A great video on the topic is [Good Action Hygiene by Mike Ryan](https://www.youtube.com/watch?v=JmnsEvoy-gY) It's for NgRx, but the same naming conventions apply to NGXS.

## Group your actions

Don't suffix your actions:

```ts
export class AddTodo {
  static readonly type = '[Todo] Add';

  constructor(public payload: any) {}
}

export class EditTodo {
  static readonly type = '[Todo] Edit';

  constructor(public payload: any) {}
}

export class FetchAllTodos {
  static readonly type = '[Todo] Fetch All';
}

export class DeleteTodo {
  static readonly type = '[Todo] Delete';

  constructor(public id: number) {}
}
```

here we group similar actions into the `Todo` namespace. In this case just import namespace instead of multiple action classes in same file.

```ts
const ACTION_SCOPE = '[Todo]';

export namespace TodoActions {
  export class Add {
    static readonly type = `${ACTION_SCOPE} Add`;

    constructor(public payload: any) {}
  }

  export class Edit {
    static readonly type = `${ACTION_SCOPE} Edit`;

    constructor(public payload: any) {}
  }

  export class FetchAll {
    static readonly type = `${ACTION_SCOPE} Fetch All`;
  }

  export class Delete {
    static readonly type = `${ACTION_SCOPE} Delete`;

    constructor(public id: number) {}
  }
}
```


# Action Schematics

You can generate an `action` using the command as seen below:

```bash
ng generate @ngxs/store:actions
```

Running this command will prompt you to create an "Action" with the options as they are listed in the table below.

Alternatively, you can provide the options yourself.

```bash
ng generate @ngxs/store:actions --name NAME_OF_YOUR_ACTION
```

| Option | Description                                  | Required | Default Value        |
| ------ | -------------------------------------------- | :------: | -------------------- |
| --name | The name of the actions                      |    Yes   |                      |
| --path | The path to create the actions               |    No    | App's root directory |
| --flat | Boolean flag to indicate if a dir is created |    No    | `false`              |

🪄 **This command will**:

* Create an action with the given options

> Note: If the --flat option is false, the generated files will be organized into a directory named using the kebab case of the --name option. For instance, 'MyActions' will be transformed into 'my-actions'.


# Actions Life Cycle

This document describes the life cycle of actions, after reading it you should have a better understanding of how NGXS handles actions and what stages they may be at.

## Theory

Any action in NGXS can be in one of four states, these states are `DISPATCHED`, `SUCCESSFUL`, `ERRORED`, `CANCELED`, think of it as a finite state machine.

![Actions FSM](/files/-LkQ3Z6be3uvYnhKIEFJ)

NGXS has an internal stream of actions. When we dispatch any action using the following code:

```ts
store.dispatch(new GetNovels());
```

The internal actions stream emits an object called `ActionContext`, that has 2 properties:

```ts
{
  action: GetNovelsInstance,
  status: 'DISPATCHED'
}
```

There is an action stream listener that filters actions by `DISPATCHED` status and invokes the appropriate handlers for this action. After all processing for the action has completed it generates a new `ActionContext` with the following `status` value:

```ts
{
  action: GetNovelsInstance,
  status: 'SUCCESSFUL'
}
```

The observable returned by the `dispatch` method is then triggered after the action is handled "successfully" and, in response to this observable, you are able to do the actions you wanted to do on completion of the action.

If the `GetNovels` handler throws an error, for example:

```ts
@Action(GetNovels)
getNovels() {
  throw new Error('This is just a simple error!');
}
```

Then the following `ActionContext` will be created:

```ts
{
  action: GetNovelsInstance,
  status: 'ERRORED'
}
```

Actions can be both synchronous and asynchronous, for example if you send a request to your API and wait for the response. Asynchronous actions are handled in parallel, synchronous actions are handled one after another.

What about the `CANCELED` status? Only asynchronous actions can be canceled, this means that the new action was dispatched before the previous action handler finished doing some asynchronous job. Canceling actions can be achieved by providing options to the `@Action` decorator:

```ts
export class NovelsState {
  @Selector()
  static getNovels(state: Novel[]) {
    return state;
  }

  constructor(private novelsService: NovelsService) {}

  @Action(GetNovels, { cancelUncompleted: true })
  getNovels(ctx: StateContext<Novel[]>) {
    return this.novelsService.getNovels().pipe(
      tap(novels => {
        ctx.setState(novels);
      })
    );
  }
}
```

Imagine a component where you've got a button that dispatches the `GetNovels` action on click:

```ts
@Component({
  selector: 'app-novels',
  template: `
    @for (novel of novels(); track novel) {
      <app-novel [novel]="novel" />
    }

    <button (click)="getNovels()">Get novels</button>
  `,
  standalone: true,
  imports: [NovelComponent]
})
export class NovelsComponent {
  novels = this.store.selectSignal(NovelsState.getNovels);

  constructor(private store: Store) {}

  getNovels() {
    this.store.dispatch(new GetNovels());
  }
}
```

If you click the button twice - two actions will be dispatched and the previous action will be canceled because it's asynchronous. This works exactly the same as `switchMap`. If we didn't use NGXS - the code would look as follows:

```ts
@Component({
  selector: 'app-novels',
  template: `
    @for (novel of novels(); track novel) {
      <app-novel [novel]="novel" />
    }

    <button #button>Get novels</button>
  `
})
export class NovelsComponent implements OnInit {
  button = viewChild.required('button');

  novels = signal<Novel[]>([]);

  constructor(private novelsService: NovelsService) {}

  ngOnInit() {
    fromEvent(this.button().nativeElement, 'click')
      .pipe(switchMap(() => this.novelsService.getNovels()))
      .subscribe(novels => {
        this.novels.set(novels);
      });
  }
}
```

## Asynchronous actions

Let's talk more about asynchronous actions, imagine a simple state that stores different genres of books and has the following code:

```ts
export interface BooksStateModel {
  novels: Book[];
  detectives: Book[];
}

export class GetNovels {
  static type = '[Books] Get novels';
}

export class GetDetectives {
  static type = '[Books] Get detectives';
}

@State<BooksStateModel>({
  name: 'books',
  defaults: {
    novels: [],
    detectives: []
  }
})
@Injectable()
export class BooksState {
  constructor(private booksService: BooksService) {}

  @Action(GetNovels)
  getNovels(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getNovels().pipe(
      tap(novels => {
        ctx.patchState({ novels });
      })
    );
  }

  @Action(GetDetectives)
  getDetectives(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getDetectives().pipe(
      tap(detectives => {
        ctx.patchState({ detectives });
      })
    );
  }
}
```

Let's say that you dispatch `GetNovels` and `GetDetectives` actions separately like this:

```ts
store
  .dispatch(new GetNovels())
  .subscribe(() => {
    ...
  });

store
  .dispatch(new GetDetectives())
  .subscribe(() => {
    ...
  });
```

You could correctly assume that the request for `GetNovels` would be dispatched before `GetDetectives`. This is true due to the synchronous nature of the dispatch, but their action handlers are asynchronous so you can't be sure which HTTP response would return first. In this example we dispatch the `GetNovels` action before `GetDetectives`, but if the call to fetch novels takes longer then the `novels` property will be set after `detectives`. The `store.dispatch` function returns an observable that can be used to respond to the completion of each of these actions.

Alternatively you could dispatch an array of actions:

```ts
store
  .dispatch([
    new GetNovels(),
    new GetDetectives()
  ])
  .subscribe(() => {
    ...
  });
```

The order of dispatch would be the same as the previous example, but in this code we are able to subscribe to an observable from the `store.dispatch` function that will fire only when both actions have completed. The below diagram demonstrates how asynchronous actions are handled under the hood:

![Life cycle](/files/-LkQ3Z7UqKjOCF6LbKlt)

## Error life cycle

So, how are errors handled in this regard? Let's say that you dispatch multiple actions at the same time like this:

```ts
store
  .dispatch([
    new GetNovelById(id), // action handler throws `new Error(...)`
    new GetDetectiveById(id)
  ])
  .subscribe({
    next: () => {
      // they will never see me
    },
    error: error => {
      console.log(error); // `Error` that was thrown by the `getNovelById` handler
    }
  });
```

Because at least one action throws an error NGXS returns an error to the `onError` observable callback and neither the `onNext` or `onComplete` callbacks would be called.

## Asynchronous Actions continued - "Fire and forget" vs "Fire and wait"

In NGXS, when you do asynchronous work you should return an `Observable` or `Promise` from your `@Action` method that represents that asynchronous work (and completion). The completion of the action will then be bound to the completion of the asynchronous work. If you use the `async/await` javascript syntax then NGXS will know about the completion because an `async` method returns the `Promise` for you. If you return an `Observable` NGXS will subscribe to the observable for you and bind the action's completion lifecycle event to the completion of the `Observable`.

The "fire-and-forget" approach refers to performing asynchronous work inside an action handler without returning anything from the method. This approach is not recommended because state writes are no longer allowed once the action handler "completes". When you don't return anything (effectively using a `void` return type), state writes are disabled immediately after the synchronous part of the handler finishes executing:

```ts
@Action(GetNovels)
getNovels(ctx: StateContext<BooksStateModel>) {
  this.booksService.getNovels().subscribe(novels => {
    // This code will not patch the state because `patchState` is disabled
    // after the `GetNovels` handler has finished executing.
    ctx.patchState({ novels });
  });
}
```

Another more common use case of using the "fire and forget" approach would be when you dispatch a new action inside a handler and you don't want to wait for the "child" action to complete. For example, if we want to load detectives right after novels but we don't want the completion of our `GetNovels` action to wait for the detectives to load then we would have the following code:

```ts
export class BooksState {
  constructor(private booksService: BooksService) {}

  @Action(GetNovels)
  getNovels(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getNovels().pipe(
      tap(novels => {
        ctx.patchState({ novels });
        ctx.dispatch(new GetDetectives());
      })
    );
  }

  @Action(GetDetectives)
  getDetectives(ctx: StateContext<BooksStateModel>) {
    return this.booksService.getDetectives().pipe(
      tap(detectives => {
        ctx.patchState({ detectives });
      })
    );
  }
}
```

Here the `GetDetectives` action would be dispatched just before the `GetNovels` action completes. The `GetDetectives` action is just a "fire and forget" as far as the `GetNovels` action is concerned. To be clear, NGXS will wait for a response from the `getNovels` service call, then it will populate a new state with the returned novels, then it will dispatch the new `GetDetectives` action (which kicks off another asynchronous request), and then `GetNovels` would move into its' success state (without waiting for the completion of the `GetDetectives` action):

```ts
store.dispatch(new GetNovels()).subscribe(() => {
  // they will see me, but detectives will be still loading in the background
});
```

If you want the `GetNovels` action to wait for the `GetDetectives` action to complete, you will have to use `mergeMap` operator (or any operator that maps to the inner `Observable`, like `concatMap`, `switchMap`, `exhaustMap`) so that the `Observable` returned by the `@Action` method has bound its completion to the inner action's completion:

```ts
@Action(GetNovels)
getNovels(ctx: StateContext<BooksStateModel>) {
  return this.booksService.getNovels().pipe(
    tap(novels => {
      ctx.patchState({ novels });
    }),
    mergeMap(() => ctx.dispatch(new GetDetectives()))
  );
}
```

Often this type of code can be made simpler by converting to Promises and using the `async/await` syntax. The same method would be as follows:

```ts
@Action(GetNovels)
async getNovels(ctx: StateContext<BooksStateModel>) {
  const novels = await firstValueFrom(this.booksService.getNovels());
  ctx.patchState({ novels });
  await firstValueFrom(ctx.dispatch(new GetDetectives()));
}
```

Note: leaving out the final `await` keyword here would cause this to be "fire and forget" again.

## Handling Cancellation with AbortSignal

When using `cancelUncompleted`, NGXS provides an `abortSignal` property on the `StateContext` (available in v21+) that allows you to detect and respond to action cancellation. This is especially useful when working with async/await:

```ts
@Action(GetNovels, { cancelUncompleted: true })
async getNovels(ctx: StateContext<Novel[]>) {
  // Perform async work
  const novels = await firstValueFrom(this.booksService.getNovels());

  // Check if action was canceled before updating state
  if (ctx.abortSignal.aborted) {
    return; // Exit gracefully without updating state
  }

  ctx.setState(novels);
}
```

The `abortSignal` can also be passed directly to the Fetch API:

```ts
@Action(SearchBooks, { cancelUncompleted: true })
async searchBooks(ctx: StateContext<BooksStateModel>, action: SearchBooks) {
  try {
    const response = await fetch(`/api/books?q=${action.query}`, {
      signal: ctx.abortSignal // Automatically cancels the request
    });

    const books = await response.json();
    ctx.patchState({ books });
  } catch (error) {
    if (error.name === 'AbortError') {
      return; // Gracefully handle cancellation
    }
    throw error;
  }
}
```

When you return an Observable from an action handler, NGXS automatically unsubscribes when the action is canceled, so you don't need to manually check the `abortSignal`.

For more details on action cancellation, see the [Cancellation guide](/master/concepts/actions/cancellation).

## Summary

In summary - any dispatched action starts with the status `DISPATCHED`. Next, NGXS looks for handlers that listen to this action, if there are any — NGXS invokes them and processes the return value and errors. If the handler has done some work and has not thrown an error, the status of the action changes to `SUCCESSFUL`. If something went wrong while processing the action (for example, if the server returned an error) then the status of the action changes to `ERRORED`. And if an action handler is marked as `cancelUncompleted` and a new action has arrived before the old one was processed then NGXS interrupts the processing of the first action and sets the action status to `CANCELED`.


# Actions Stream

Before reading this article, we advise you to become acquainted with the [actions life cycle](/master/concepts/actions/actions-life-cycle).

Event sourcing involves modeling the state changes made by applications as an immutable sequence or “log” of events.\
Instead of focusing on current state, you focus on the changes that have occurred over time. It is the practice of\
modeling your system as a sequence of events. In NGXS, we called this the Actions Stream.

Typically actions directly correspond to state changes but it can be difficult to always make your component react\
based on state. As a side effect of this paradigm, we end up creating lots of intermediate state properties\
to do things like reset a form/etc. The Actions Stream lets us drive our components based on state along with events\
that are emitted.

For example, if we were to have a shopping cart and we were to delete an item out of it you might want to show\
a notification that it was successfully removed. In a pure state driven application, you might create some kind\
of message array to make the dialog show up. With the Actions Stream, we can respond to the action directly.

The Actions Stream is an Observable that receives all the actions dispatched before the state takes any action on it.

Actions in NGXS also have a lifecycle. Since any potential action can be async we tag actions showing when they are "DISPATCHED", "SUCCESSFUL", "CANCELED" or "ERRORED". This gives you the ability to react to actions at different points in their existence.

Since the actions stream is an Observable, we can use the following operators inside a `pipe(..)`:

* `ofAction`: triggers when any of the below lifecycle events happen
* `ofActionDispatched`: triggers when an action has been dispatched
* `ofActionSuccessful`: triggers when an action has been completed successfully
* `ofActionCanceled`: triggers when an action has been canceled
* `ofActionErrored`: triggers when an action has caused an error to be thrown
* `ofActionCompleted`: triggers when an action has been completed whether it was successful or not (returns completion summary)

All of the above pipes return the original `action` in the observable except for the `ofActionCompleted` pipe which returns some summary information for the completed action. This summary is an object with the following interface:

```ts
interface ActionCompletion<T = any> {
  action: T;
  result: {
    successful: boolean;
    canceled: boolean;
    error?: Error;
  };
}
```

Below is a action handler that filters for `RouteNavigate` actions and then tells the router to navigate to that\
route.

```ts
import { Injectable, inject } from '@angular/core';
import { Actions, ofActionDispatched } from '@ngxs/store';

@Injectable({ providedIn: 'root' })
export class RouteHandler implements OnDestroy {
  private destroy$ = new Subject<void>();

  constructor() {
    const actions$ = inject(Actions);
    const router = inject(Router);

    actions$
      .pipe(ofActionDispatched(RouteNavigate), takeUntil(this.destroy$))
      .subscribe(({ payload }) => router.navigate([payload]));
  }

  ngOnDestroy(): void {
    this.destroy$.next();
  }
}
```

Remember to ensure that you inject the `RouteHandler` somewhere in your application for DI to set things up. If you want this to occur during application startup, this can also be accomplished using the new `ENVIRONMENT_INITIALIZER` token:

```ts
import { ApplicationConfig, ENVIRONMENT_INITIALIZER, inject } from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: ENVIRONMENT_INITIALIZER,
      multi: true,
      useValue: () => inject(RouteHandler)
    }
  ]
};
```

The Actions Stream can also be utilized in components. For example, considering the cart deletion scenario, we could use the following code:

```ts
@Component({ ... })
export class CartComponent {
  constructor() {
    const actions$ = inject(Actions);

    actions$.pipe(ofActionSuccessful(CartDelete)).subscribe(() => alert('Item deleted'));
  }
}
```

Also, remember to unsubscribe from the Actions Stream at the end:

```ts
@Component({ ... })
export class CartComponent {
  constructor() {
    const actions$ = inject(Actions);

    actions$
      .pipe(ofActionSuccessful(CartDelete), takeUntilDestroyed())
      .subscribe(() => alert('Item deleted'));
  }
}
```


# Cancellation

If you have an async action, you may want to cancel a previous Observable if the action has been dispatched again. This is useful for canceling previous requests like in a typeahead.

## Basic

For basic scenarios, we can use the `cancelUncompleted` action decorator option.

```ts
import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService, private actions$: Actions) {}

  @Action(FeedAnimals, { cancelUncompleted: true })
  get(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.get(action.payload).pipe(
      tap((res) => ctx.setState(res))
    ));
  }
}
```

## Ignoring

`cancelUncompleted` cancels the previous uncompleted invocation and lets the new dispatch proceed (similar to RxJS's `switchMap`). If instead you want to ignore new dispatches while the previous invocation is still uncompleted (similar to RxJS's `exhaustMap`), use the `ignoreUncompleted` option:

```ts
import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals, { ignoreUncompleted: true })
  get(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.get(action.payload).pipe(
      tap((res) => ctx.setState(res))
    ));
  }
}
```

`cancelUncompleted` and `ignoreUncompleted` are mutually exclusive - setting both on the same handler throws an error.

## Using AbortSignal

Starting from NGXS v21, the `StateContext` includes an `abortSignal` property that provides a standardized way to handle cancellation of asynchronous operations. This is particularly useful when working with `cancelUncompleted` actions.

### Why AbortSignal?

The `AbortSignal` provides a standard browser API to detect and respond to cancellations. When an action marked with `cancelUncompleted: true` is canceled (because a new instance was dispatched), the `abortSignal` will be aborted, allowing you to:

* Check cancellation status in async/await code
* Pass the signal to fetch requests for automatic cancellation
* Clean up resources gracefully
* Avoid unnecessary state updates

### With Async/Await

When using async/await, check `ctx.abortSignal.aborted` after await points to handle cancellation:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

export class FetchAnimals {
  static readonly type = '[Zoo] Fetch Animals';
}

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FetchAnimals, { cancelUncompleted: true })
  async fetchAnimals(ctx: StateContext<ZooStateModel>) {
    // Perform async work
    const animals = await this.animalService.getAnimals();

    // Check if canceled before updating state
    if (ctx.abortSignal.aborted) {
      console.log('Action was canceled, skipping state update');
      return;
    }

    ctx.setState({ animals });
  }
}
```

### With Fetch API

The `AbortSignal` works seamlessly with the Fetch API:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

export class SearchAnimals {
  static readonly type = '[Zoo] Search Animals';
  constructor(public query: string) {}
}

@State<ZooStateModel>({
  defaults: {
    animals: [],
    loading: false
  }
})
@Injectable()
export class ZooState {
  @Action(SearchAnimals, { cancelUncompleted: true })
  async searchAnimals(ctx: StateContext<ZooStateModel>, action: SearchAnimals) {
    ctx.patchState({ loading: true });

    try {
      // Pass the abort signal directly to fetch
      const response = await fetch(`/api/animals?q=${action.query}`, {
        signal: ctx.abortSignal
      });

      const animals = await response.json();
      ctx.patchState({ animals, loading: false });
    } catch (error) {
      // Handle abort gracefully
      if (error.name === 'AbortError') {
        console.log('Search was canceled');
        return; // Don't update state or rethrow
      }

      // Handle other errors
      ctx.patchState({ loading: false });
      throw error;
    }
  }
}
```

### With Observables

When you return an Observable from an action handler, NGXS automatically unsubscribes when the `abortSignal` is aborted. You don't need to manually check the signal:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { tap } from 'rxjs';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals, { cancelUncompleted: true })
  feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    // Observable will be automatically unsubscribed if action is canceled
    return this.animalService
      .get(action.payload)
      .pipe(tap(animals => ctx.setState({ animals })));
  }
}
```

## Advanced

For more advanced cases, we can use normal Rx operators.

```ts
import { Injectable } from '@angular/core';
import { State, Action, Actions, ofAction } from '@ngxs/store';
import { tap } from 'rxjs';

@State<ZooStateModel>({
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService, private actions$: Actions) {}

  @Action(FeedAnimals)
  get(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.get(action.payload).pipe(
      tap((res) => ctx.setState(res)),
      takeUntil(this.actions$.pipe(ofAction(RemoveTodo)))
    ));
  }
}
```


# Dynamic Action Handlers

Sometimes you need to attach action handlers dynamically after state initialization. For example, you might want to:

* Add action handlers conditionally based on runtime conditions
* Add action handlers for lazy-loaded modules
* Add temporary action handlers that can be removed later

How is a Dynamic Action Handler different to what the [Actions Stream](/master/concepts/actions/actions-stream) gives you?

* It gives you the ability to make changes to state from your handler
* It participates in the standard [actions life cycle](/master/concepts/actions/actions-life-cycle)
  * The result of the handler will affect the completion result of the action
  * The life cycle for the action will only complete once all dynamic handlers have completed too

NGXS provides the `ActionDirector` service for registering Dynamic Action Handlers.

## DISCLAIMER: Before you use it...

Please bear in mind that this is a power user feature, and should not be used as a replacement for the typical action declarations within a state.

* Overuse of Dynamic Action Handlers can lead to an application that is hard to understand and hard to determine the exact behavior of a state at a specific point in time
* Co-location of the handlers with a state class is a massive benefit for a clean and predictable codebase. When using Dynamic Action Handlers, please consider this fact and try to honour this principle
* The main intended use of this feature is for plugins and utilities that enhance state, so if you are doing something else, please check that you can't solve your problem with the simpler state constructs
* Another potential use is for the lazy loading of action handler logic. This is a very specialised optimisation and should only be used if lazy loading the entire state with a route is not sufficient

## The ActionDirector Service

The `ActionDirector` allows you to attach action handlers to a state at any point after initialization and gives you the ability to detach them when no longer needed.

### Attaching an Action Handler

```ts
import { ActionDirector, createSelector } from '@ngxs/store';
import { inject, Injectable } from '@angular/core';

// State token
const COUNTRIES_STATE_TOKEN = new StateToken<string[]>('countries');

// Action
export class AddCountry {
  static readonly type = '[Countries] Add Country';

  constructor(readonly country: string) {}
}

@Injectable({ providedIn: 'root' })
export class CountryService {
  private actionDirector = inject(ActionDirector);
  private handle: { detach: () => void } | null = null;

  // Attach the action handler
  attachCountryHandler() {
    if (this.handle) return; // Already attached

    this.handle = this.actionDirector.attachAction(
      COUNTRIES_STATE_TOKEN,
      AddCountry,
      (ctx, action) => {
        // Update state
        ctx.setState(countries => [...countries, action.country]);
      }
    );
  }

  // Detach the action handler when no longer needed
  detachCountryHandler() {
    this.handle?.detach();
    this.handle = null;
  }
}
```

### When to Use Dynamic Action Handlers

Dynamic action handlers are useful in several scenarios:

1. **Plugin systems**: Allow plugins to register their own action handlers
2. **Lazy-loaded features**: Attach action handlers when a feature module is loaded
3. **Temporary behaviors**: Create handlers that only exist for a specific duration
4. **Conditional action handling**: Enable action handlers based on runtime conditions

### The detach Function

The `attachAction` method returns an object with a `detach` function that can be called to remove the action handler. This enables proper cleanup and prevents memory leaks.

```ts
// Example of attaching and later detaching a handler
const handle = actionDirector.attachAction(STATE_TOKEN, SomeAction, (ctx, action) => {
  // Handler logic
});

// Later, when the handler is no longer needed:
handle.detach();
```


# Monitoring Unhandled Actions

We can know if we have dispatched some actions which haven't been handled by any of the NGXS states. This is useful to monitor if we dispatch actions at the right time. For instance, dispatched actions might be coming from the WebSocket, but the action handler is located within the feature state that has not been registered yet. This will let us know that we should either register the state earlier or do anything else from the code perspective because actions are not being handled.

This may be enabled by adding the `withNgxsDevelopmentOptions` to `provideStore`:

```ts
import { provideStore, withNgxsDevelopmentOptions } from '@ngxs/store';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsDevelopmentOptions({
        warnOnUnhandledActions: true
      })
    )
  ]
};
```

If you are still using modules, include the `NgxsDevelopmentModule` plugin in your root app module:

```ts
import { NgxsModule, NgxsDevelopmentModule } from '@ngxs/store';

@NgModule({
  imports: [
    NgxsModule.forRoot([]),
    NgxsDevelopmentModule.forRoot({
      warnOnUnhandledActions: true
    })
  ]
})
export class AppModule {}
```

Setting `warnOnUnhandledActions` to a truthy value will tell the logger to warn on any unhandled action.

## Ignoring Certain Actions

We can ignore specific actions that should not be logged if they have never been handled. For instance, if we're using the `@ngxs/router-plugin` and don't care about router actions like `RouterNavigation`, then we may add it to the `ignore` array:

```ts
import { provideStore, withNgxsDevelopmentOptions } from '@ngxs/store';
import { RouterNavigation, RouterCancel } from '@ngxs/router-plugin';

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore(
      [],
      withNgxsDevelopmentOptions({
        warnOnUnhandledActions: true
      })
    )
  ]
};
```

> 💡 It's best to import this module only in development mode. This may be achieved using environment imports. See [dynamic plugins](/master/recipes/dynamic-plugins).

Ignored actions can be also expanded in lazy modules. The `@ngxs/store` exposes the `NgxsUnhandledActionsLogger` for these purposes:

```ts
import { inject, ENVIRONMENT_INITIALIZER } from '@angular/core';
import { NgxsUnhandledActionsLogger } from '@ngxs/store';

declare const ngDevMode: boolean;

const providers = [provideStates([LazyState])];

if (ngDevMode) {
  providers.push({
    provide: ENVIRONMENT_INITIALIZER,
    multi: true,
    useValue: () => {
      const unhandledActionsLogger = inject(NgxsUnhandledActionsLogger);
      unhandledActionsLogger.ignoreActions(LazyAction);
    }
  });
}

export const routes: Routes = [
  {
    path: '',
    component: LazyComponent,
    providers
  }
];
```

The `ngDevMode` is a specific variable provided by Angular in development mode and by Angular CLI (to Terser) in production mode. This allows tree-shaking `NgxsUnhandledActionsLogger` stuff since the `NgxsDevelopmentModule` is imported only in development mode. It's never functional in production mode.


# STATE

States are classes that define a state container.

## Defining a State

States are classes along with decorators to describe metadata and action mappings. To define a state container, let's create an ES2015 class and decorate it with the `State` decorator.

```ts
import { Injectable } from '@angular/core';
import { State } from '@ngxs/store';

@State<string[]>({
  name: 'animals',
  defaults: []
})
@Injectable()
export class AnimalsState {}
```

In the state decorator, we define some metadata about the state. These options include:

* `name`: The name of the state slice. Note: The name is a required parameter and must be unique for the entire application. Names must be object property safe, (e.g. no dashes, dots, etc).
* `defaults`: Default set of object/array for this state slice.
* `children`: Child sub state associations (it's **deprecated** and slated for removal in the future, so it's advisable not to use it in newer applications).

Our states can also participate in dependency injection. This is hooked up automatically so all you need to do is inject your dependencies in the constructor.

```ts
@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feed: false
  }
})
@Injectable()
export class ZooState {
  constructor(private zooService: ZooService) {}
}
```

## (Optional) Defining State Token

Optionally, you can choose to replace the `name` of your state with a state token:

```ts
const ZOO_STATE_TOKEN = new StateToken<ZooStateModel>('zoo');

@State({
  name: ZOO_STATE_TOKEN,
  defaults: {
    feed: false
  }
})
@Injectable()
export class ZooState {
  constructor(private zooService: ZooService) {}
}
```

This slightly more advanced approach has some benefits which you can read more about in the [State Token](/master/concepts/state/token) section.

## Defining Actions

Our states listen to actions via an `@Action` decorator. The action decorator accepts an action class or an array of action classes.

### Simple Actions

Let's define a state that will listen to a `FeedAnimals` action to toggle whether the animals have been fed:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';
}

export interface ZooStateModel {
  feed: boolean;
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feed: false
  }
})
@Injectable()
export class ZooState {
  @Action(FeedAnimals)
  feedAnimals(ctx: StateContext<ZooStateModel>) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      feed: !state.feed
    });
  }
}
```

The `feedAnimals` function has one argument called `ctx` with a type of `StateContext<ZooStateModel>`. This context state has a slice pointer and several functions and properties for managing state:

* `getState()`: Returns the freshest state slice from the global store. When performing async operations the state is always fresh when you call this method.
* `setState()`: Sets the entire state to a new value
* `patchState()`: Patches only the specified properties
* `dispatch()`: Dispatches one or more actions
* `abortSignal`: An `AbortSignal` tied to the action's lifecycle (available in NGXS v21+). This allows you to handle cancellation of async operations, especially useful with `cancelUncompleted` actions.

It's important to note that the `getState()` method will always return the freshest state slice from the global store each time it is accessed. This ensures that when we're performing async operations the state is always fresh. If you want a snapshot, you can always clone the state in the method.

### Actions with a payload

Actions can also pass along metadata that has to do with the action. Say we want to pass along how much hay and carrots each zebra needs.

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';

// This is an interface that is part of your domain model
export interface ZebraFood {
  name: string;
  hay: number;
  carrots: number;
}

// naming your action metadata explicitly makes it easier to understand what the action
// is for and makes debugging easier.
export class FeedZebra {
  static readonly type = '[Zoo] FeedZebra';

  constructor(public zebraToFeed: ZebraFood) {}
}

export interface ZooStateModel {
  zebraFood: ZebraFood[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    zebraFood: []
  }
})
@Injectable()
export class ZooState {
  @Action(FeedZebra)
  feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      zebraFood: [
        ...state.zebraFood,
        // this is the new ZebraFood instance that we add to the state
        action.zebraToFeed
      ]
    });
  }
}
```

In this example, we have a second argument that represents the action and we destructure it to pull out the name, hay, and carrots which we then update the state with.

There is also a shortcut `patchState` function to make updating the state easier. In this case, you only pass it the properties you want to update on the state and it handles the rest. The above function could be reduced to this:

```ts
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
  const state = ctx.getState();
  ctx.patchState({
    zebraFood: [
      ...state.zebraFood,
      action.zebraToFeed,
    ]
  });
}
```

The `setState` function can also be called with a function which will be given the existing state and should return the new state. All immutability concerns need to be honoured by this function.

For comparison, here are the two ways that you can invoke the `setState` function...\
With a new constructed state value:

```ts
@Action(MyAction)
addValue(ctx: StateContext, { payload }: MyAction) {
  ctx.setState({ ...ctx.getState(), value: payload  });
}
```

With a function that returns the new state value:

```ts
@Action(MyAction)
addValue(ctx: StateContext, { payload }: MyAction) {
  ctx.setState((state) => ({ ...state, value: payload }));
}
```

You may ask *"How is this valuable?"*. Well, it opens the door for refactoring of your immutable updates into `state operators` so that your code can become more declarative as opposed to imperative. You can find more details in our [state operators](https://www.ngxs.io/advanced/operators) documentation.

As another example you could use a library like [immer](https://github.com/mweststrate/immer) that can handle the immutability updates for you and provide a different way of expressing your immutable update through direct mutation of a draft object. We can use this external library because it supports the same signature as our `state operators` through their curried `produce` function. Here is the example from above expressed in this way:

```ts
import produce from 'immer';

// in class ZooState ...
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
  ctx.setState(produce((draft) => {
    draft.zebraFood.push(action.zebraToFeed);
  }));
}
```

Here the `produce` function from the `immer` library is called with just a single parameter so that it returns its [curried form](https://immerjs.github.io/immer/curried-produce) that will take a value and return a new value with all the expressed changes applied.

This approach can also allow for the creation of well named helper functions that can be shared between handlers that require the same type of update. The above example could be refactored to this:

```ts
// in class ZooState ...
@Action(FeedZebra)
feedZebra(ctx: StateContext<ZooStateModel>, action: FeedZebra) {
  ctx.setState(addToZebraFood(action.zebraToFeed));
}

// defined elsewhere
import produce from 'immer';

function addToZebraFood(itemToAdd) {
  return produce((draft) => {
    draft.zebraFood.push(itemToAdd);
  });
}
```

### Async Actions

Actions can perform async operations and update the state after an operation.

Typically in Redux your actions are pure functions and you have some other system like a saga or an effect to perform these operations and dispatch another action back to your state to mutate it. There are some reasons for this, but for the most part it can be redundant and just add boilerplate. The great thing here is we give you the flexibility to make that decision yourself based on your requirements.

Let's take a look at a simple async action:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { tap } from 'rxjs';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';

  constructor(public animalsToFeed: string) {}
}

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals)
  feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.feed(action.animalsToFeed).pipe(
      tap(animalsToFeedResult => {
        const state = ctx.getState();
        ctx.setState({
          ...state,
          feedAnimals: [...state.feedAnimals, animalsToFeedResult]
        });
      })
    );
  }
}
```

In this example, we reach out to the animal service and call `feed` and then call `setState` with the result. Remember that we can guarantee that the state is fresh since the state property is a getter back to the current state slice.

You might notice we returned the Observable and just did a `tap`. If we return the Observable, the framework will automatically subscribe to it for us, so we don't have to deal with that ourselves. Additionally, if we want the stores `dispatch` function to be able to complete only once the operation is completed, we need to return that so it knows that.

Observables are not a requirement, you can use promises too. We could swap that observable chain to look like this:

```ts
import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';

  constructor(public animalsToFeed: string) {}
}

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals)
  async feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    const result = await this.animalService.feed(action.animalsToFeed);
    const state = ctx.getState();
    ctx.setState({
      ...state,
      feedAnimals: [...state.feedAnimals, result]
    });
  }
}
```

### Handling Cancellation in Async Actions

When using `cancelUncompleted` with async/await, you can use the `abortSignal` property to gracefully handle cancellation:

```ts
import { Injectable } from '@angular/core';
import { State, Action } from '@ngxs/store';

export class FeedAnimals {
  static readonly type = '[Zoo] FeedAnimals';

  constructor(public animalsToFeed: string) {}
}

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  @Action(FeedAnimals, { cancelUncompleted: true })
  async feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    const result = await this.animalService.feed(action.animalsToFeed);

    // Check if action was canceled before updating state
    if (ctx.abortSignal.aborted) {
      return; // Exit gracefully without updating state
    }

    const state = ctx.getState();
    ctx.setState({
      ...state,
      feedAnimals: [...state.feedAnimals, result]
    });
  }
}
```

### Dispatching Actions From Actions

If you want your action to dispatch another action, you can use the `dispatch` function that is contained in the state context object.

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { map } from 'rxjs';

export interface ZooStateModel {
  feedAnimals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    feedAnimals: []
  }
})
@Injectable()
export class ZooState {
  constructor(private animalService: AnimalService) {}

  /**
   * Simple Example
   */
  @Action(FeedAnimals)
  feedAnimals(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      feedAnimals: [...state.feedAnimals, action.animalsToFeed]
    });

    return ctx.dispatch(new TakeAnimalsOutside());
  }

  /**
   * Async Example
   */
  @Action(FeedAnimals)
  feedAnimals2(ctx: StateContext<ZooStateModel>, action: FeedAnimals) {
    return this.animalService.feed(action.animalsToFeed).pipe(
      tap(animalsToFeedResult => {
        const state = ctx.getState();
        ctx.patchState({
          feedAnimals: [...state.feedAnimals, animalsToFeedResult]
        });
      }),
      mergeMap(() => ctx.dispatch(new TakeAnimalsOutside()))
    );
  }
}
```

Notice we returned the dispatch function, this goes back to our example above with async operations and the dispatcher subscribing to the result. It is not required though.


# State Schematics

You can generate a `state` using the command as seen below:

```bash
ng generate @ngxs/store:state
```

Running this command will prompt you to create a "State" with the options as they are listed in the table below.

Alternatively, you can provide the options yourself.

```bash
ng generate @ngxs/store:state --name NAME_OF_YOUR_STATE
```

| Option    | Description                                                    | Required | Default Value               |
| --------- | -------------------------------------------------------------- | :------: | --------------------------- |
| --name    | The name of the state                                          |    Yes   |                             |
| --path    | The path to create the state                                   |    No    | App's root directory        |
| --spec    | Boolean flag to indicate if a unit test file should be created |    No    | `true`                      |
| --flat    | Boolean flag to indicate if a dir is created                   |    No    | `false`                     |
| --project | Name of the project as it is defined in your angular.json      |    No    | Workspace's default project |

> When working with multiple projects within a workspace, you can explicitly specify the `project` where you want to install the **state**. The schematic will automatically detect whether the provided project is a standalone or not, and it will generate the necessary files accordingly.

🪄 **This command will**:

* Create a state with the given options

> Note: If the --flat option is false, the generated files will be organized into a directory named using the kebab case of the --name option. For instance, 'MyState' will be transformed into 'my-state'.


# Life-cycle

States can implement life-cycle events.

## `ngxsOnChanges`

If a state implements the `NgxsOnChanges` interface, its `ngxsOnChanges` method responds when the state is (re)set.

The `ngxsOnChanges` methods of states are invoked in a topologically sorted order, going from parent to child states. Within these methods, the first parameter is the `NgxsSimpleChange` object containing the current and previous states.

```ts
export interface ZooStateModel {
  animals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState implements NgxsOnChanges {
  ngxsOnChanges(change: NgxsSimpleChange) {
    console.log('prev state', change.previousValue);
    console.log('next state', change.currentValue);
  }
}
```

## `ngxsOnInit`

If a state implements the `NgxsOnInit` interface, its `ngxsOnInit` method is invoked after the `InitState` or `UpdateState` action has been handled, depending on where the state is registered (root or feature). If your state is provided at the root level, its `ngxsOnInit` may be called immediately once the `ENVIRONMENT_INITIALIZER` token is resolved. However, it may also be called asynchronously if you handle the `InitState` action and have some asynchronous logic.

The `ngxsOnInit` methods of states are invoked in a topologically sorted order, going from parent to child states. Within these methods, the first parameter is the `StateContext`, which allows you to access the current state and dispatch actions as usual.

```ts
export interface ZooStateModel {
  animals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState implements NgxsOnInit {
  ngxsOnInit(ctx: StateContext<ZooStateModel>) {
    console.log('State initialized, now getting animals');
    ctx.dispatch(new GetAnimals());
  }
}
```

## `ngxsAfterBootstrap`

If a state implements the `NgxsAfterBootstrap` interface, its `ngxsAfterBootstrap` method will be bound to the `APP_BOOTSTRAP_LISTENER`, which is resolved after the app has been bootstrapped.

```ts
export interface ZooStateModel {
  animals: string[];
}

@State<ZooStateModel>({
  name: 'zoo',
  defaults: {
    animals: []
  }
})
@Injectable()
export class ZooState implements NgxsAfterBootstrap {
  ngxsAfterBootstrap(ctx: StateContext<ZooStateModel>) {
    console.log('The application has been fully rendered');
    ctx.dispatch(new GetAnimals());
  }
}
```

## Lifecycle sequence

After creating the state by calling its constructor, NGXS calls the lifecycle hook methods in the following sequence at specific moments:

| Hook                 | Purpose and Timing                                                                                       |
| -------------------- | -------------------------------------------------------------------------------------------------------- |
| ngxsOnChanges()      | Called *before* `ngxsOnInit()` and whenever state changes.                                               |
| ngxsOnInit()         | Called *once*, after the *first* `ngxsOnChanges()` and *before* the `APP_INITIALIZER` token is resolved. |
| ngxsAfterBootstrap() | Called *once*, after the root view and all its children have been rendered.                              |

## Feature States Order of Providers

If you have feature states they need to be registered after the root `provideStore` has been called:

```ts
// some-data-access-library/index.ts
export function provideDataAccessInvoiceLines() {
  return provideStates([InvoiceLinesState]);
}

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [provideStore(), provideDataAccessInvoiceLines()]
};
```

<details>

<summary>If you are still using modules</summary>

If you have feature modules they need to be imported after the root module:

```ts
// feature.module.ts
@NgModule({
  imports: [NgxsModule.forFeature([FeatureState])]
})
export class FeatureModule {}

// app.module.ts
@NgModule({
  imports: [NgxsModule.forRoot([]), FeatureModule]
})
export class AppModule {}
```

</details>

## APP\_INITIALIZER Stage

### Theoretical Introduction

The `APP_INITIALIZER` is just a token that references Promise factories. If you've ever used the `APP_INITIALIZER` token, then you are already familiar with its syntax:

```ts
export function appInitializerFactory() {
  return () => Promise.resolve();
}

export const appConfig: ApplicationConfig = {
  providers: [
    {
      provide: APP_INITIALIZER,
      useFactory: appInitializerFactory,
      multi: true
    }
  ]
};
```

Please refer to [this guide](https://angular.io/api/core/APP_INITIALIZER) to familiarize yourself with its functionality.

### APP\_INITIALIZER and NGXS

The `APP_INITIALIZER` token is resolved after NGXS states are registered. This is because they are registered during the resolution of the `ENVIRONMENT_INITIALIZER` token. Additionally, the `ngxsOnInit` method on states is invoked before the `APP_INITIALIZER` token is resolved. Given the following code:

```ts
@Injectable({ providedIn: 'root' })
export class ConfigService {
  private version: string | null = null;

  private http = inject(HttpClient);

  loadVersion(): Observable<string> {
    return this.http.get<string>('/api/version').pipe(
      tap(version => {
        this.version = version;
      })
    );
  }

  getVersion(): never | string {
    if (this.version === null) {
      throw new Error('"version" is not available yet!');
    }

    return this.version;
  }
}

@State<string | null>({
  name: 'version',
  defaults: null
})
@Injectable()
export class VersionState implements NgxsOnInit {
  private configService = inject(ConfigService);

  ngxsOnInit(ctx: StateContext<string | null>) {
    ctx.setState(this.configService.getVersion());
  }
}

export function appInitializerFactory() {
  const configService = inject(ConfigService);
  return () => configService.loadVersion();
}

export const appConfig: ApplicationConfig = {
  providers: [
    provideStore([VersionState]),

    {
      provide: APP_INITIALIZER,
      useFactory: appInitializerFactory,
      multi: true
    }
  ]
};
```

The example provided is for demonstration purposes and will throw an error because the `version` is not set yet. This occurs because `getVersion` is called before the version is loaded.

### Solution

There are different solutions. Let's look at the simplest. The first solution would be to use the `ngxsAfterBootstrap` method:

```ts
@State<string | null>({
  name: 'version',
  defaults: null
})
@Injectable()
export class VersionState implements NgxsAfterBootstrap {
  private configService = inject(ConfigService);

  ngxsAfterBootstrap(ctx: StateContext<string | null>) {
    ctx.setState(this.configService.getVersion());
  }
}
```

The second solution would be dispatching some `SetVersion` action right after the version is fetched:

```ts
export class SetVersion {
  static readonly type = '[Version] Set version';

  constructor(public version: string) {}
}

@State<string | null>({
  name: 'version',
  defaults: null
})
@Injectable()
export class VersionState {
  @Action(SetVersion)
  setVersion(ctx: StateContext<string | null>, action: SetVersion): void {
    ctx.setState(action.version);
  }
}

@Injectable({ providedIn: 'root' })
export class ConfigService {
  private http = inject(HttpClient);
  private store = inject(Store);

  loadVersion() {
    return this.http.get<string>('/api/version').pipe(
      tap(version => {
        this.store.dispatch(new SetVersion(version));
      })
    );
  }
}
```

### Summary

In conclusion, the `ngxsOnInit` method is useful when you need to set some calculated values on the state with access to dependency injection within the state class, but before the app is bootstrapped. This allows components to pick up available data.


# Composition

You can compose multiple stores together using class inheritance. This is quite simple:

```ts
@State({
  name: 'zoo',
  defaults: {
    type: null
  }
})
@Injectable()
class ZooState {
  @Action(Eat)
  eat(ctx: StateContext) {
    ctx.setState({ type: 'eat' });
  }
}

@State({
  name: 'stlzoo'
})
@Injectable()
class StLouisZooState extends ZooState {
  @Action(Drink)
  drink(ctx: StateContext) {
    ctx.setState({ type: 'drink' });
  }
}
```

Now when `StLouisZooState` is invoked, it will share the actions of the `ZooState`. Also all state options are inherited.


# Lazy Loading

States can be easily lazy-loaded by adding the `provideStates` function to the `Route` providers:

```ts
import { provideStates } from '@ngxs/store';

export const routes: Routes = [
  {
    path: '',
    component: AnimalsComponent,
    providers: [provideStates([AnimalsState])]
  }
];
```

If you are still using modules, you can import the `NgxsModule` using the `forFeature` method:

```ts
@NgModule({
  imports: [NgxsModule.forFeature([AnimalsState])]
})
export class LazyModule {}
```

It's important to note that when lazy-loading a state, it is registered in the global state, meaning this state object will now be persisted globally. Even though it's available globally, you should only use it within that feature component to ensure you don't create dependencies on things that may not be loaded yet.

How are feature states added to the global state graph? Assume you have a `ZoosState`:

```ts
@State<Zoo[]>({
  name: 'zoos',
  defaults: []
})
@Injectable()
export class ZoosState {}
```

And it's registered at the root level via `provideStore([ZoosState])`. Assume you've got a feature `offices` state:

```ts
@State<Office[]>({
  name: 'offices',
  defaults: []
})
@Injectable()
export class OfficesState {}
```

After the route is loaded and its providers are initialized, the global state will have the following signature if you register this state in some lazy-loaded component via `provideStates([OfficesState])`:

```ts
{
  zoos: [],
  offices: []
}
```

You can try it yourself by invoking `store.snapshot()` and printing the result to the console before and after the lazy component is loaded.

## `lazyProvider`

The `lazyProvider` function is designed to defer the registration of Angular providers until they are explicitly needed — such as when navigating to a route or triggering a guard. This is particularly useful for feature state libraries, where including providers in multiple locations could cause them to be unintentionally bundled into the initial application bundle.

```ts
import { lazyProvider } from '@ngxs/store';

const routes = [
  {
    path: 'home',
    loadComponent: () => import('./home/home.component').then(m => m.HomeComponent),
    canActivate: [
      lazyProvider(async () => (await import('path-to-state-library')).invoicesStateProvider)
    ]
  }
];
```

Exporting a provider:

```ts
// path-to-state-library/index.ts
export const invoicesStateProvider = provideStates([InvoicesState]);
```

It also supports `default` exports, which are common in dynamically imported ES modules. If the imported provider is wrapped in a default property (e.g., `export default invoicesStateProvider`), the function will automatically unwrap and register it.

```ts
// In routes
lazyProvider(() => import('path-to-state-library'));

// path-to-state-library/index.ts
const invoicesStateProvider = provideStates([InvoicesState]);
export default invoicesStateProvider;
```


# State Operators

## State Operators

### Why?

The NGXS `patchState` method is used to do [immutable object](https://en.wikipedia.org/wiki/Immutable_object) updates to the container state slice without the typical long-handed syntax. This is very neat and convenient because you do not have to use the `getState` and `setState` as well as the `Object.assign(...)`or the spread operator to update the state. The `patchState` method only offers a shallow patch and as a result is left wanting in more advanced scenarios. This is where state operators come in. The `setState` method can be passed a state operator which will be used to determine the new state.

### Basic

The basic idea of operators is that we could describe the modifications to the state using curried functions that are given any inputs that they need to describe the change and are finalized using the state slice that they are assigned to.

## Example

From theory to practice - let's take the following example:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch } from '@ngxs/store/operators';

export interface AnimalsStateModel {
  zebras: string[];
  pandas: string[];
  monkeys?: string[];
}

export class CreateMonkeys {
  static readonly type = '[Animals] Create monkeys';
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: {
    zebras: [],
    pandas: []
  }
})
@Injectable()
export class AnimalsState {
  @Action(CreateMonkeys)
  createMonkeys(ctx: StateContext<AnimalsStateModel>) {
    ctx.setState(
      patch<AnimalsStateModel>({
        monkeys: []
      })
    );
  }
}
```

The `patch` operator expresses the intended modification quite nicely and returns a function that will apply these modifications as a new object based on the provided state. In order to understand what this is doing let's express this in a long handed form:

```ts
  // For demonstration purposes! This long handed form is not needed from NGXS v3.4 onwards.
  @Action(CreateMonkeys)
  createMonkeys(ctx: StateContext<AnimalsStateModel>) {
    const state = ctx.getState();
    ctx.setState({
      ...state,
      monkeys: []
    });
  }
```

### Supplied State Operators

This is not the only operator, we introduce much more that can be used along with or in place of `patch`.

If the state slice you're patching might be `null` or `undefined`, regular `patch` will throw because it tries to spread a non-object. `safePatch` handles that case by treating a missing state as an empty object `{}` before applying the patch:

```ts
safePatch<T extends object>(patchSpec: PatchSpec<T>): StateOperator<T>
```

This is handy when a slice of state is optional and may not have been initialized yet. For example:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, safePatch } from '@ngxs/store/operators';

export interface UserPreferences {
  theme: string;
  language: string;
}

export interface UserStateModel {
  name: string;
  preferences: UserPreferences | null;
}

export class SetTheme {
  static readonly type = '[User] Set theme';
  constructor(public theme: string) {}
}

@State<UserStateModel>({
  name: 'user',
  defaults: {
    name: '',
    preferences: null
  }
})
@Injectable()
export class UserState {
  @Action(SetTheme)
  setTheme(ctx: StateContext<UserStateModel>, action: SetTheme) {
    ctx.setState(
      patch<UserStateModel>({
        // safePatch handles preferences being null — no need to initialize it first
        preferences: safePatch<UserPreferences>({ theme: action.theme })
      })
    );
  }
}
```

With plain `patch`, the action above would fail if `preferences` is `null`. With `safePatch`, it treats `null` as `{}` and produces `{ theme: 'dark', language: undefined }` — or whatever the patch spec describes. This also works when nesting `safePatch` inside itself for deeply optional structures.

If you want to update the value of a property based on some condition - you can use `iif`, it's signature is:

```ts
iif<T>(
  condition: Predicate<T> | boolean,
  trueOperatorOrValue: StateOperator<T> | T,
  elseOperatorOrValue?: StateOperator<T> | T
): StateOperator<T>
```

If you want to update an item in the array using an operator or value - you can use `updateItem`, it's signature is:

```ts
updateItem<T>(selector: number | Predicate<T>, operator: T | StateOperator<T>): StateOperator<T[]>
```

If you want to update **all** items in the array that match a predicate - use `updateItems`. Unlike `updateItem`, which stops at the first match, `updateItems` walks the entire array and applies the operator or value to every matching element:

```ts
updateItems<T>(selector: Predicate<T>, operator: T | StateOperator<T>): StateOperator<T[]>
```

For example, to mark every inactive animal as active in one `setState` call:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, updateItems } from '@ngxs/store/operators';

export interface Animal {
  name: string;
  active: boolean;
}

export interface AnimalsStateModel {
  animals: Animal[];
}

export class ActivateAll {
  static readonly type = '[Animals] Activate all';
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: { animals: [] }
})
@Injectable()
export class AnimalsState {
  @Action(ActivateAll)
  activateAll(ctx: StateContext<AnimalsStateModel>) {
    ctx.setState(
      patch<AnimalsStateModel>({
        animals: updateItems<Animal>(animal => !animal.active, patch({ active: true }))
      })
    );
  }
}
```

If you want to remove an item from an array by index or predicate - you can use `removeItem`:

```ts
removeItem<T>(selector: number | Predicate<T>): StateOperator<T[]>
```

If you want to remove **all** items in the array that match a predicate - use `removeItems`. Unlike `removeItem`, which stops at the first match, `removeItems` walks the entire array and drops every qualifying element:

```ts
removeItems<T>(selector: Predicate<T>): StateOperator<T[]>
```

For example, to purge all inactive animals in one `setState` call:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, removeItems } from '@ngxs/store/operators';

export interface Animal {
  name: string;
  active: boolean;
}

export interface AnimalsStateModel {
  animals: Animal[];
}

export class PurgeInactive {
  static readonly type = '[Animals] Purge inactive';
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: { animals: [] }
})
@Injectable()
export class AnimalsState {
  @Action(PurgeInactive)
  purgeInactive(ctx: StateContext<AnimalsStateModel>) {
    ctx.setState(
      patch<AnimalsStateModel>({
        animals: removeItems<Animal>(animal => !animal.active)
      })
    );
  }
}
```

If you want to insert an item to an array, optionally before a specified index - use `insertItem` operator:

```ts
insertItem<T>(value: T, beforePosition?: number): StateOperator<T[]>
```

If you want to append specified items to the end of an array - the `append` operator is suitable for that:

```ts
append<T>(items: T[]): StateOperator<T[]>
```

It's also possible to compose multiple operators into a single operator that would apply each consecutively using `compose`:

```ts
compose<T>(...operators: StateOperator<T>[]): StateOperator<T>
```

These operators introduce a new way of declarative state mutation.

### Advanced Example

Let's look at more advanced examples:

```ts
import { Injectable } from '@angular/core';
import { State, Action, StateContext } from '@ngxs/store';
import { patch, append, removeItem, insertItem, updateItem } from '@ngxs/store/operators';

export interface AnimalsStateModel {
  zebras: string[];
  pandas: string[];
}

export class AddZebra {
  static readonly type = '[Animals] Add zebra';
  constructor(public payload: string) {}
}

export class RemovePanda {
  static readonly type = '[Animals] Remove panda';
  constructor(public payload: string) {}
}

export class ChangePandaName {
  static readonly type = '[Animals] Change panda name';
  constructor(public payload: { name: string; newName: string }) {}
}

@State<AnimalsStateModel>({
  name: 'animals',
  defaults: {
    zebras: ['Jimmy', 'Jake', 'Alan'],
    pandas: ['Michael', 'John']
  }
})
@Injectable()
export class AnimalsState {
  @Action(AddZebra)
  addZebra(ctx: StateContext<AnimalsStateModel>, action: AddZebra) {
    ctx.setState(
      patch<AnimalsStateModel>({
        zebras: append<string>([action.payload])
      })
    );
  }

  @Action(RemovePanda)
  removePanda(ctx: StateContext<AnimalsStateModel>, action: RemovePanda) {
    ctx.setState(
      patch<AnimalsStateModel>({
        pandas: removeItem<string>(name => name === action.payload)
      })
    );
  }

  @Action(ChangePandaName)
  changePandaName(ctx: StateContext<AnimalsStateModel>, action: ChangePandaName) {
    ctx.setState(
      patch<AnimalsStateModel>({
        pandas: updateItem<string>(
          name => name === action.payload.name,
          action.payload.newName
        )
      })
    );
  }
}
```

You will see that in each case above the state operators are wrapped within a call to the `patch` operator. This is only done because of the convenience that the `patch` state operator provides for targeting a nested property of the state.

### Typing Operators

Specifying types for the `patch` operator is always necessary when doing nested updates. You can face cases when the `patch` operator cannot infer the nested type structure. Let's look at the following state:

```ts
export class UpdateLine1 {
  static readonly type = '[Address] Update line1';
  constructor(readonly line1: string) {}
}

export interface AddressStateModel {
  country: {
    city: {
      address: {
        line1: string;
      };
    };
  };
}

@State<AddressStateModel>({
  name: 'address',
  defaults: {
    country: {
      city: {
        address: {
          line1: ''
        }
      }
    }
  }
})
@Injectable()
export class AddressState {
  @Action(UpdateLine1)
  updateLine1(ctx: StateContext<AddressStateModel>, action: UpdateLine1) {
    ctx.setState(
      patch({
        country: patch({
          city: patch({
            address: patch({
              line1: action.line1
            })
          })
        })
      })
    );
  }
}
```

If we don't specify the type explicitly for `patch`, all objects are inferred as `unknown`, meaning that TypeScript cannot tell us that we're doing something wrong or using the wrong type. The correct way of specifying nested types is shown below:

```ts
export class UserState {
  @Action(UpdateLine1)
  updateLine1(ctx: StateContext<AddressStateModel>, action: UpdateLine1) {
    ctx.setState(
      patch<AddressStateModel>({
        country: patch<AddressStateModel['country']>({
          city: patch<AddressStateModel['country']['city']>({
            address: patch<AddressStateModel['country']['city']['address']>({
              line1: action.line1
            })
          })
        })
      })
    );
  }
}
```

If we change `country` to `Qcountry` (intentional mistake), the compiler will tell us `Object literal may only specify known properties, but 'Qcountry' does not exist`. The same technique may be used with other operators if they cannot infer the type.

💡 Tip: we can specify the state model type and chain properties to get the desired type. Like in the example above.

### Custom Operators

You can also define your own operators for updates that are common to your domain. For example:

```ts
function addEntity(entity: Entity): StateOperator<EntitiesStateModel> {
  return (state: Readonly<EntitiesStateModel>) => {
    return {
      ...state,
      entities: { ...state.entities, [entity.id]: entity },
      ids: [...state.ids, entity.id]
    };
  };
}

interface CitiesStateModel {
  // ...
}

@State<CitiesStateModel>({
  name: 'cities',
  defaults: {
    entities: {},
    ids: []
  }
})
@Injectable()
export class CitiesState {
  @Action(AddCity)
  addCity(ctx: StateContext<CitiesStateModel>, action: AddCity) {
    ctx.setState(addEntity<CitiesStateModel>(action.payload.city));
  }
}
```

Here you can see that the developer chose to define a convenience method called `addEntity` for doing a common state modification. This operator could also have also been defined using existing operators like so:

```ts
function addEntity(entity: Entity): StateOperator<EntitiesStateModel> {
  return patch<EntitiesStateModel>({
    entities: patch({ [entity.id]: entity }),
    ids: append([entity.id])
  });
}
```

As you can see, state operators are very powerful to start moving your immutable state updates to be more declarative and expressive. Enhancing the overall maintainability and readability of your state class code.

### Snippets

Check this [section](/master/concepts/state/operators-1) for more operators that you can add to your application.

### Relevant Articles

[NGXS State Operators](https://medium.com/ngxs/ngxs-state-operators-8b339641b220)


# Custom State Operators

In this section you will find state operators that are not part of the library but can be very helpful in your app.

## upsertItem

Inserts or updates an item in an array depending on whether it exists.

### Usage

```ts
ctx.setState(
  patch<FoodModel>({
    foods: upsertItem<Food>(f => f.id === foodId, food)
  })
);
```

### State Operator Code

```ts
import { StateOperator } from '@ngxs/store';
import {
  compose,
  iif,
  insertItem,
  NoInfer,
  patch,
  Predicate,
  updateItem
} from '@ngxs/store/operators';

export function upsertItem<T>(
  selector: number | Predicate<T>,
  upsertValue: NoInfer<T>
): StateOperator<T[]> {
  return compose<T[]>(
    items => <T[]>(items || []),
    iif<T[]>(
      items => Number(selector) === selector,
      iif<T[]>(
        items => selector < items.length,
        updateItem(selector, patch(upsertValue)),
        insertItem(upsertValue, <number>selector)
      ),
      iif<T[]>(
        items => items.some(<Predicate<T>>selector),
        updateItem(selector, patch(upsertValue)),
        insertItem(upsertValue)
      )
    )
  );
}
```

### Collaborate with your awesome operator!

Have you identified an use case for a new operator? If that's the case you can collaborate sharing it here! To learn more read this [issue](https://github.com/ngxs/store/issues/926) and submit your PR with your operator as part of the *Snippets* section.


# Shared State

Shared state is the ability to get state from one state container and use its properties in another state container in a read-only manner. While it's not natively supported it can be accomplished.

Let's say you have 2 stores: Animals and Preferences. In your preferences store, which is backed by `localstorage`, you have the sort order for the Animals. You need to get the state from the preferences in order to be able to sort your animals. This is achievable with `selectSnapshot`.

```ts
@State<PreferencesStateModel>({
  name: 'preferences',
  defaults: {
    sort: [{ prop: 'name', dir: 'asc' }]
  }
})
@Injectable()
export class PreferencesState {
  @Selector()
  static getSort(state: PreferencesStateModel) {
    return state.sort;
  }
}

@State<AnimalStateModel>({
  name: 'animals',
  defaults: [
    animals: []
  ]
})
@Injectable()
export class AnimalState {

  constructor(private store: Store) {}

  @Action(GetAnimals)
  getAnimals(ctx: StateContext<AnimalStateModel>) {
    const state = ctx.getState();

    // select the snapshot state from preferences
    const sort = this.store.selectSnapshot(PreferencesState.getSort);

    // do sort magic here
    return state.sort(sort);
  }

}
```


# State Token

A state token can be used as a representation of a state class without referring directly to the state class itself. When creating an StateToken you will provide the location that the state should be stored on your state tree. You can also set a default state model type of the parameterized type `T`, which can assist with ensuring the type safety of referring to your state in your application. The state token is declared as follows:

```ts
import { StateToken } from '@ngxs/store';

const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');
```

Or if you choose to not expose the model of your state class to the rest of the application then you can pass the type as `unknown` or `any` (this is useful if you want to keep all knowledge of the structure of your state class model private).

```ts
const TODOS_STATE_TOKEN = new StateToken<unknown>('todos');
```

If you use pass this token as the `name` property in your `@State` declaration (or if the path specified matches your `name` property then you can use this token to refer to this state class from other parts of your application (in your selectors, or in plugins like the storage plugin that need to refer to a state class). The token can be used in your `@State` declaration as follows:

```ts
export interface TodoStateModel {
  title: string;
  completed: boolean;
}

export const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');

// Note: the @State model type is inferred from in your token.
@State({
  name: TODOS_STATE_TOKEN,
  defaults: []
})
@Injectable()
export class TodosState {
  // ...
}
```

A state token with a model type provided can be used in other parts of your application to improve type safety in the following aspects:

* Improved type checking for `@State`, `@Selector` in a state class

```ts
export interface TodoStateModel {
  title: string;
  completed: boolean;
}

export const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');

@State({
  name: TODOS_STATE_TOKEN,
  defaults: [] // if you specify the wrong state type, will be a compilation error
})
@Injectable()
export class TodosState {
  @Selector([TODOS_STATE_TOKEN]) // if you specify the wrong state type, will be a compilation error
  static getCompletedList(state: TodoStateModel[]): TodoStateModel[] {
    return state.filter(todo => todo.completed);
  }
}
```

The following code demonstrates mismatched types that will be picked up as compilation errors:

```ts
export const TODOS_STATE_TOKEN = new StateToken<TodoStateModel[]>('todos');

@State({
  name: TODOS_STATE_TOKEN,
  defaults: {} // compilation error - array was expected, inferred from the token type
})
@Injectable()
export class TodosState {
  @Selector([TODOS_STATE_TOKEN]) // compilation error - TodoStateModel[] does not match string[]
  static getCompletedList(state: string[]): string[] {
    return state;
  }
}
```

* Improved type inference for `store.selectSignal, store.select, store.selectOnce, store.selectSnapshot`

```ts
@Component(/**/)
class AppComponent implements OnInit {
  constructor(private store: Store) {}

  ngOnInit(): void {
    const todosSignal = this.store.selectSignal(TODOS_STATE_TOKEN); // infers type Signal<TodoStateModel[]>
    const todos = this.store.selectSnaphot(TODOS_STATE_TOKEN); // infers type TodoStateModel[]
    const todos$ = this.store.select(TODOS_STATE_TOKEN); // infers type Observable<TodoStateModel[]>
    const oneTodos$ = this.store.selectOnce(TODOS_STATE_TOKEN); // infers type Observable<TodoStateModel[]>
  }
}
```


# Immutability Helpers

Redux is a tiny pattern that represents states as immutable objects. Redux was originally designed for React. Most Redux concepts, such as pure functions, are centered around the React ecosystem. Nowadays Redux is not directly related to React.

The cornerstone of Redux is immutability. Immutability is an amazing pattern to minimise unpredictable behaviour in our code. We're not going to cover functional programming in this article. However we're going to look at very useful packages that are called "immutability helpers".

## The Problem

Most developers have to deal with, so called, "deep objects" and most important follow the immutability concept, when it comes to changing the value of some deeply nested property. Given the following code:

```ts
export interface Task {
  title: string;
  dates: {
    startDate: string;
    dueDate: string;
  };
}

export interface TrelloStateModel {
  tasks: {
    [taskId: string]: Task;
  };
}
@State<TrelloStateModel>({
  name: 'trello',
  defaults: {
    tasks: {}
  }
})
@Injectable()
export class TrelloState {}
```

Let's imagine that we're faced with the task of changing the `dueDate` property:

```ts
export class UpdateDueDate {
  static readonly type = '[Trello] Update due date';
  constructor(
    public taskId: string,
    public dueDate: string
  ) {}
}
```

Let's see how we would implement the `updateDueDate` action handler:

```ts
export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    ctx.setState(state => ({
      tasks: {
        ...state.tasks,
        [action.taskId]: {
          ...state.tasks[action.taskId],
          dates: {
            ...state.tasks[action.taskId].dates,
            dueDate: action.dueDate
          }
        }
      }
    }));
  }
}
```

This code will work but unfortunately it is complicated to maintain and understand. It's not self-descriptive and will be daunting for new developers.

## Solutions

There are different ways to improve this code. Let us look at a few different packages that can help in this regard.

### State Operators

[State operators](/master/concepts/state/operators) are first-class immutability helpers that NGXS provides out of the box. The `patch` operator will become your best friend in case of choosing state operators as your immutability helpers. Let's see how we could re-write the above code with the help of the `patch` state operator:

```ts
import { patch } from '@ngxs/store/operators';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    ctx.setState(
      patch({
        tasks: patch({
          [action.taskId]: patch({
            dates: patch({
              dueDate: action.dueDate
            })
          })
        })
      })
    );
  }
}
```

### immer

`immer` is a very popular library that allows you to make changes to immutable objects as if they were mutable. The below code shows how to write the same code with the help of Immer:

```ts
import { produce } from 'immer';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = produce(ctx.getState(), draft => {
      draft.tasks[action.taskId].dates.dueDate = action.dueDate;
    });

    ctx.setState(state);
  }
}
```

Immer's `produce` function can be also used as a state operator:

```ts
import { produce } from 'immer';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    ctx.setState(
      produce(draft => {
        draft.tasks[action.taskId].dates.dueDate = action.dueDate;
      })
    );
  }
}
```

You may notice how much less code this is and how much better it looks. From the `immer` repository:

> Using Immer is like having a personal assistant; he takes a letter (the current state) and gives you a copy (draft) to jot changes onto. Once you are done, the assistant will take your draft and produce the real immutable, final letter for you (the next state).

[Immer repository](https://github.com/immerjs/immer)

### immutability-helper

`immutability-helper` is a small package that lets you mutate a copy of data without changing the original source:

```ts
import update from 'immutability-helper';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = update(ctx.getState(), {
      tasks: {
        [action.taskId]: {
          dates: {
            dueDate: {
              $set: action.dueDate
            }
          }
        }
      }
    });

    ctx.setState(state);
  }
}
```

[immutability-helper repository](https://github.com/kolodny/immutability-helper)

### object-path-immutable

`object-path-immutable` is a small library that allows you to modify deep object properties without modifying the original object. Let's look at how we could write the same code using this library:

```ts
import immutable from 'object-path-immutable';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = immutable.set(
      ctx.getState(),
      `tasks.${action.taskId}.dates.dueDate`,
      action.dueDate
    );

    ctx.setState(state);
  }
}
```

[object-path-immutable repository](https://github.com/mariocasciaro/object-path-immutable)

### immutable-assign

`immutable-assign` is a lightweight library that pursues the same goal. Its syntax is similar to `immer`'s:

```ts
import * as iassign from 'immutable-assign';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = iassign(ctx.getState(), state => {
      state.tasks[action.taskId].dates.dueDate = action.dueDate;
      return state;
    });

    ctx.setState(state);
  }
}
```

[immutable-assign repository](https://github.com/engineforce/ImmutableAssign)

### Ramda

Ramda is a great library for functional programming and it is used in a large number of projects. This example might be useful for people who use both Ramda and NGXS in their projects:

```ts
import * as R from 'ramda';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const property = R.lensPath(['tasks', action.taskId, 'dates', 'dueDate']);
    const state = R.set(property, action.dueDate, ctx.getState());
    ctx.setState(state);
  }
}
```

[Ramda repository](https://github.com/ramda/ramda)

### icepick

`icepick` is a zero-dependency library for working with immutable collections. Given the following re-written code:

```ts
import * as icepick from 'icepick';

export class TrelloState {
  @Action(UpdateDueDate)
  updateDueDate(ctx: StateContext<TrelloStateModel>, action: UpdateDueDate) {
    const state = icepick.setIn(
      ctx.getState(),
      ['tasks', action.taskId, 'dates', 'dueDate'],
      action.dueDate
    );

    ctx.setState(state);
  }
}
```

[icepick repository](https://github.com/aearly/icepick)

## Summary

We have looked at several different libraries that might be helpful in accompanying the concept of immutability. Choose the right one for your needs.


# Error Handling




---

[Next Page](/llms-full.txt/1)

