LogoLogo
Latest Release
Latest Release
  • NGXS
    • Overview
  • INTRODUCTION
    • WHY
    • INSTALLATION
    • STARTER KIT
    • SCHEMATICS
  • CONCEPTS
    • STORE
      • Overview
      • Store Schematics
      • Store Options
      • Error Handling
      • Meta Reducers
    • ACTIONS
      • Overview
      • Action Schematics
      • Actions Life Cycle
      • Action Handlers
      • Cancellation
      • Monitoring Unhandled Actions
    • STATE
      • Overview
      • State Schematics
      • Life-cycle
      • Composition
      • Lazy Loading
      • State Operators
      • Custom State Operators
      • Shared State
      • State Token
      • Immutability Helpers
      • Error Handling
      • Sub States
    • SELECT
      • Overview
      • Mapped Sub States
      • Optimizing Selectors
      • Selector Utils
      • Error Handling
      • Signals
      • Select Decorator
  • STYLE GUIDE
  • PLUGINS
    • Overview
    • CLI
    • Logger
    • Devtools
    • Storage
    • Forms
    • Web Socket
    • Router
    • HMR
  • RECIPES
    • Authentication
    • Caching
    • Component Events from NGXS
    • Debouncing Actions
    • Dynamic Plugins
    • Module Federation
    • Unit Testing
    • RxAngular Integration
    • Zoneless Server-Side Rendering
  • COMMUNITY & LABS
    • COMMUNITY
      • FAQ
      • Resources
      • Contributors
      • Contributing
      • Sponsors
    • NGXS LABS
      • Overview
  • DEPRECATIONS
    • Inject Container State Deprecation
    • Sub States Deprecation
    • Select Decorator Deprecation
  • CHANGELOG
Powered by GitBook
On this page
  • Internal Actions
  • Simple Action
  • Actions with Metadata
  • Dispatching Actions
  • How should you name your actions?
  • Commands
  • Event examples
  • Group your actions
Edit on GitHub
  1. CONCEPTS

ACTIONS

PreviousMeta ReducersNextAction Schematics

Last updated 1 year ago

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 events.

  2. @@UPDATE_STATE - a new 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:

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.

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

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

Group your actions

Don't suffix your actions:

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.

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) {}
  }
}

See documentation for how to dispatch actions.

A great video on the topic is It's for NgRx, but the same naming conventions apply to NGXS.

ngxsOnInit Life-cycle
lazy-loaded state
Store
Good Action Hygiene by Mike Ryan