Simple Angular app using ngrx 8+ store and effects factory methods

Chirag Rupani
4 min readJul 10, 2019

In this story, we will use ngrx/store and ngrx/effects in angular app using simple To Do App sample. We will use latest factory methods that will simplify code significantly. The code sample for this story is at https://github.com/ChiragRupani/Ngrx8StoreSample.

Let’s get started. First set up Angular app if haven’t done already:

Create New App

ng new todoapp --routing

Note about ngrx 8 version and dependencies:

ngrx version 8 has following minimum version requirements:

  • Angular version 8.x and Angular CLI version 8.0.2
  • TypeScript version 3.4.x
  • RxJS version 6.4.0

Install @ngrx/store and @ngrx/effects

npm install @ngrx/store @ngrx/effects

ToDo Component

We will create new ToDo folder. We will add To Do Component using Angular CLI and move it under ToDo/component folder.

ng g c ToDo

ToDo Directory Structure

We are using simple directory structure as below:

Directory structure

Lets delve in each of files.

To Do Model

The To Do Model contains only two fields - Title and IsCompleted.

To Do State

ToDoState interface contains ToDos the list of model. It represents current state of the model. Here, we can store the other status like Loading, Loaded, Updating, Updated, Error etc. while performing CRUD operations. Also, we have initialization function variable that will set up the initial state.

To Do Action

Action are messages that are dispatched — to update the state in the store. The createAction function returns a function which when called returns Action object. The props method is used to define any additional payload. Action creators provide a consistent and type-safe way to create an action.

For now, consider first two actions viz., GetToDoAction and CreateToDoAction actions. The other actions Begin and Success becomes relevant when we start adding effects . The first parameter is string which is type of action and used to identify the action dispatched in reducer. The second optional parameter is function which is generic and so any object can be defined, the type checking checks for corresponding properties wherever that action creator is used or dispatched. For this example, we have defined single property — payload .

To Do Reducer

Reducer is pure function, it is roughly equivalent to table in the database in the way it provides a slice of data. The Reducer function takes current state and dispatched action and return new state. It will return current state as it is when action doesn’t require any updates like Get Actions. The Reducer will never modify the current state.

The Reducer is based on three core redux principles:

  1. Single source of truth — state of entire application is stored in single store
  2. State is read-only — state can only be updated by dispatching Actions
  3. Changes are made with pure functions — Reducers never mutates previous state, it always returns the state based on current state and action

Prior to ngrx 8 we have switch statements on action type. Now, it is simplified using createReducer factory method. The first parameter is initial state. Then we can pass any number of on reducers that receives current state and action props and return new state. There is exported ToDoReducer function, it is necessary as function calls are not supported by the AOT compiler.

We have used Object destructuring to get payload property. We also Triple dots also called as spread operator (MSDocs and MDN) to return new state. It is syntactic sugar for Object.assign(). What it simply does is — it takes properties of source object (first parameter) and updates its properties based on subsequent parameters, later properties overriding earlier ones and returns new target object — the way we avoid mutation.

Register ToDo store

Add below line in imports array of @NgModule (usually App Module) class

StoreModule.forRoot({ todos: ToDoReducer })

To Do Component

Here, we are showing list of ToDos and then form to create new ToDo. We can access store in constructor as it is globally registered when we imported in App Module. From store we select todos and subscribe to some of properties of ToDo state. Then we are dispatching actions like this.store.dispatch(ToDoActions.BeginGetToDoAction()) and optionally passing payload.

Usually, we are calling API from back end to save and retrieve the data — ToDo in this case. So, we will required another piece to complete the flow that is @ngrx/effects An Effect listens for actions dispatched from Store, performs operations and then dispatches new Action to Store. Effect isolates side effects from components. we have already installed @ngrx/effects at beginning while installing @ngrx/store .

To Do Effects

Notice, here with Ngrx8 we have used createEffect factory method to create effects. We are no longer required to add @Effect decorator (if you did the effect may be called twice), the factory method handles it. To work with Effect we need to create a class decorated with @Injectable() and then inject Actions into it. An injectable Actions service provides an observable stream of all actions dispatched after the latest state has been reduced. We are calling Web API using HttpClient get and post calls. In real example, the logic for calling API could be moved to service class

when .ofType() gets called, it subscribes to the source stream of actions and pushes matching actions to the resulting stream. In short, the effect subscribes to each of action types once, so the corresponding effect would be called when that action is called.

We are using Merge Map to flatten inner observable, where we are making HTTP Call and fetching/submitting the data. Then we are returning Observable<Action> with Action of type Success or Error for corresponding CRUD operation.

We are returning action SuccessGetToDoAction in case of success and ErrorToDoAction in case of error. This action will be implicitly dispatched to the store.

Register Effect

Add below line in imports array of @NgModule (usually App Module) class

EffectsModule.forRoot([ToDoEffects])

That’s it. Go ahead run the application and verify if ToDo App is working.

Thanks for the reading!

--

--

Chirag Rupani

Full stack .Net developer, Web developer and Web Surfer.