Enterprise Angular Applications with NgRx and Nx
  • Introduction
  • Introduction
    • Introduction
    • Course Description
    • Resources
    • 0 - Environment Setup
    • 1a - Brief Introduction To Angular
    • 1b - Brief Introduction To Angular
    • 1c - Brief Introduction To Angular
    • 2 - Creating an Nx Workspace
    • 3 - Generating components and Nx lib
    • 4 - Add JSON server
    • 5 - Angular Services
    • 6 - Angular Material
    • 7 - Reactive Forms
    • 8 - Layout Lib and BehaviorSubjects
    • 9 - Route Guards and Products Lib
    • 10 - NgRx Introduction
    • 11 - Adding NgRx to Nx App
    • 12 - Strong Typing the State and Actions
    • 13 - NgRx Effects
    • 14 - NgRx Selectors
    • 15 - Add Products NgRx Feature Module
    • 16 - Entity State Adapter
    • 17 - Router Store
    • 18 - Deploying An Nx Monorepo
Powered by GitBook
On this page
  • 1. Add Login Action Creators
  • Action Hygiene
  • 2. Add default state and interface
  1. Introduction

12 - Strong Typing the State and Actions

In this section we explore Strongly Typing the State and Actions

Previous11 - Adding NgRx to Nx AppNext13 - NgRx Effects

Last updated 3 years ago

The say: The createAction function returns a function, that when called returns an object in the shape of the Action interface. The props method is used to define any additional metadata needed for the handling of the action. Action creators provide a consistent, type-safe way to construct an action that is being dispatched.

1. Add Login Action Creators

libs/auth/src/lib/+state/auth.actions.ts
import { createAction, props } from '@ngrx/store';
import { Authenticate, User } from '@demo-app/data-models';

export enum AuthActionTypes {
  Login = '[Auth Page] Login',
  LoginSuccess = '[Auth API] Login Success',
  LoginFail = '[Auth API] Login Fail'
}

export const login = createAction(
  AuthActionTypes.Login,
  props<{ payload: Authenticate }> ()
);

export const loginSuccess = createAction(
  AuthActionTypes.LoginSuccess,
  props<{ payload: User }>()
);

export const loginFailure = createAction(
  AuthActionTypes.LoginFail,
  props<{ payload: any }>()
);

Action Hygiene

  • Actions should capture unique events not commands

  • Try not to reuse actions and make generic actions

  • Suffix your Action types with their source so you know where they are dispatched from like Login = '[Login Page] Login'

  • Let effects and reducers be the decision maker not the component and add multiple cases to a switch statement or effects.

  • Avoid action sub typing by adding conditional information to a property of an action payload by making multiple actions for each case. This makes it easier to test and avoids complicated conditional logic in effects and reducers.

  • Write actions first

2. Add default state and interface

  • Update state interface

libs/auth/src/lib/+state/auth.reducer.ts
//----- ABBREVIATED-----//

/**
 * Interface for the 'Auth' data used in
 *  - AuthState, and
 *  - authReducer
 */
export interface AuthData {
  loading: boolean;
  user: User;
  error: Error
}

/**
 * Interface to the part of the Store containing AuthState
 * and other information related to AuthData.
 */
export interface AuthState {
  readonly auth: AuthData;
}

//----- ABBREVIATED-----//
  • Also, update the create reducer function to this:

libs/auth/src/lib/+state/auth.reducer.ts
//----- ABBREVIATED-----//

const authReducer = createReducer(
  initialState,
  on(AuthActions.login, (state) => ({ ...state, loading: true })),
  on(AuthActions.loginSuccess, (state) => ({
    ...state,
    user: AuthActions.loginSuccess,
    loading: false,
  })),
  on(AuthActions.loginFailure, (state) => ({
    ...state,
    user: null,
    loading: false,
  }))
);

//----- ABBREVIATED-----//

Great presentation on Actions

official docs
https://www.youtube.com/watch?v=JmnsEvoy-gY&t=5s