These are the core building units of the ngrx flow. Each of them takes care of a part of the process of starting an operation to changing our state and retrieving data.
npm install@ngrx/core@ngrx/store@ngrx/effects@ngrx/store-devtools@ngrx/router-store--save
- store-devtools. Some powerful tooling for debugging.
- router-store. Keeps the state of the angular router in the store.
1.Actions
In the store object, you have a function to dispatch (trigger) actions. Actions are classes that implements the NGRX Action interface. These Action classes have two properties
import { createAction, props } from '@ngrx/store'; export enum LoginActions { login: [Login Page] Login // [Source] Event } export const login = createAction( LoginActions.login, // type props<{ username: string; password: string }>() // payload );
onSubmit(username: string, password: string) { store.dispatch(login({ username: username, password: password })); }type: it’s a read only string describing what the action stand for. For example: ‘[User] Get User Name’
payload: the type of this property depends on what type of data this action needs to send to the reducer. In the case of the previous example, is going to be a string containing the user name. Not all actions needs a payload.
2.Reducers
Reducers are pure functions in that they produce the same output for a given input. They are without side effects and handle each state transition synchronously. Each reducer function takes the latest Action dispatched, the current state, and determines whether to return a newly modified state or the original state. This guide shows you how to write reducer functions, register them in your Store, and compose feature states.
There are a few consistent parts of every piece of state managed by a reducer.
- An interface or type that defines the shape of the state.
- The arguments including the initial state or current state and the current action.
- The functions that handle state changes for their associated action(s).
import { Action, createReducer, on } from '@ngrx/store'; import * as ScoreboardPageActions from '../actions/scoreboard-page.actions'; //shape of the state according to what you are capturing export interface State { home: number; away: number; } //The initial state gives the state an initial value export const initialState: State = { home: 0, away: 0, }; const scoreboardReducer = createReducer( initialState, on(ScoreboardPageActions.homeScore, state => ({ ...state, home: state.home + 1 })), on(ScoreboardPageActions.awayScore, state => ({ ...state, away: state.away + 1 })), on(ScoreboardPageActions.resetScore, state => ({ home: 0, away: 0 })), on(ScoreboardPageActions.setScores, (state, { game }) => ({ home: game.home, away: game.away })) ); export function reducer(state: State | undefined, action: Action) { return scoreboardReducer(state, action); }
3.Effect
Effects are an RxJS powered side effect model for Store. Effects use streams to provide new sources of actions to reduce state based on external interactions such as network requests, web socket messages and time-based events.
In a service-based Angular application, components are responsible for interacting with external resources directly through services. Instead, effects provide a way to interact with those services and isolate them from the components. Effects are where you handle tasks such as fetching data, long-running tasks that produce multiple events, and other external interactions where your components don't need explicit knowledge of these interactions.
- An injectable Actions service that provides an observable stream of all actions dispatched after the latest state has been reduced.
- Metadata is attached to the observable streams using the createEffect function. The metadata is used to register the streams that are subscribed to the store. Any action returned from the effect stream is then dispatched back to the Store.
- Actions are filtered using a pipeable ofType operator. The ofType operator takes one or more action types as arguments to filter on which actions to act upon.
- Effects are subscribed to the Store observable.
- Services are injected into effects to interact with external APIs and handle streams.
import { Injectable } from '@angular/core'; import { Actions, createEffect, ofType } from '@ngrx/effects'; import { of } from 'rxjs'; import { map, mergeMap, catchError } from 'rxjs/operators'; import { MoviesService } from './movies.service'; @Injectable() export class MovieEffects { loadMovies$ = createEffect(() => this.actions$.pipe( ofType('[Movies Page] Load Movies'), mergeMap(() => this.moviesService.getAll() .pipe( map(movies => ({ type: '[Movies API] Movies Loaded Success', payload: movies })), catchError(() => of({ type: '[Movies API] Movies Loaded Error' })) ) ) ) ); constructor( private actions$: Actions, private moviesService: MoviesService ) {} }
4.Selectors
Selectors are pure functions used for obtaining slices of store state. @ngrx/store provides a few helper functions for optimizing this selection. Selectors provide many features when selecting slices of state:
more detail : https://ngrx.io/guide/store/selectors
5.Store
A store is an object (an instance of the ngrx Store class) that brings the things we mentioned before (Actions, Reducers, Selectors) together. For example, when an action is dispatched (using the store object dispatch function), the store is the one finding and executing the appropriate reducer.
It is also the one holding the application state.
