NgRx support for TypeScript

Supported APIs

NgRx is supported only for versions ≥ 8.x:

npm package API name
@ngrx/store createAction
@ngrx/store createActionGroup
@ngrx/store createReducer
@ngrx/store createSelector
@ngrx/effects createEffect

Examples

Action support

Actions are usually defined in an action.ts file. Actions are abstractions that represent some event. Note that no object is created by our analyzer for the action, however, callLinks may be added when action instances are used. Here is an example of action creation:  

actions.ts

import { createActionGroup, props, createAction } from '@ngrx/store';

export const BooksActions = createActionGroup({
  source: 'Books',
  events: {
    'Add Book': props<{ bookId: string }>(),
    'Remove Book': props<{ bookId: string }>(),  
  },
});


export const increment = createAction('[Counter Component] Increment');

Actions can be called through the APIs as follows:

foo.ts

import { BooksActions, increment } from './actions';

function my_remove_book(id){
    BooksActions.removeBook({id})
}

function my_increment(){
   increment()
}

An action can be configured to trigger the execution of some source code when the action is called. A reducer will make the state of some variable dependent on some actions. Whenever an action is executed, the corresponding handler is executed to update a state.

reducer.ts

import { createReducer, on } from '@ngrx/store';

import { BooksActions, increment } from './actions';
import { Book } from '../book-list/books.model';

export const initialState: ReadonlyArray<Book> = [];

function handle_removeBook(state, { bookId }){
   //...
}

function handle_increment(state, { bookId }){
   //...
}
export const booksReducer = createReducer(
  initialState,
  on(BooksActions.removeBook, handle_removeBook),
  on(increment, handle_increment)
);

analyzing the previous files you will get the following results:

…an effect can also be triggered by an action. The com.castsoftware.typescript checks the parameter of any OfType call within a createEffect call and evaluates the corresponding action. A call link is added between any object dispatching an action to the function given as parameter of the createEffect call. For instance when analyzing the following with the previous codes: 

effect.ts

import { createEffect, on } from '@ngrx/effects';
import { BooksActions, BooksApiActions } from './actions';
loadMovies$ = createEffect(() => this.actions$.pipe(
    ofType(BooksActions.removeBook)
    //...
    )
  );

a callLink from the caller of the action to the arrow function in the createEffect is created:

createSelector

A selector allows the extraction of some data from a state. It is defined as follows:

books.selector.ts

import { createSelector, createFeatureSelector } from '@ngrx/store';

function my_extract_book(books, collection){
   return collection.map((id) => books.find((book) => book.id === id)!);
}

export const selectBookCollection = createSelector(
  selectBooks,
  selectCollectionState,
  my_extract_book
);

..whenever the selector is used within a select call from the Store:

module.ts

import { selectBookCollection } from './books.selector';
import { Store } from '@ngrx/store';

export class AppComponent {

  
  my_select(){
    bookCollection$ = this.store.select(selectBookCollection);
  }
  
  constructor(private booksService: GoogleBooksService, private store: Store) {}

}

…a callLink is created from the caller of the select to the arrow function provided as the function given in the last argument of the createSelector call:

Known limitations

  • The standard way of defining and calling actions for NgRx versions < 8.x (as presented on the NgRx documentation page) is not supported (although it is still available in later versions). 
  • @ngrx/router-store is not supported
  • @ngrx/entity is not supported