- June 25, 2018
- Posted by: Bhoomi Bhalani
- Category: Web Development
At the core of Redux is the state container, which we call the store. The store is simply an object that hold’s our application’s state. It’s a tree structure, think directories, that contains all of the entities that our application uses. Some of these entities might include things like users, orders, and line items. In Redux we only have a single store that contains the state for the entire application. Let’s dive into the core concepts of the Redux pattern, and show some examples using NgRx.
We need to understand a few core concepts before we can start using NgRx:
An action is an object that represents an intent to mutate or change the state of our application. An action could be:
- Loading data from a REST API.
- Opening a sidebar or showing a dialog.
- Routing to a different view.
The reducer in the Redux pattern has the responsibility of acting upon an action to mutate the state of our application. We only mutate the state of our application within a
So far we can define action objects that intend to mutate the state of our application, and we can create
reducer() pure functions that will mutate the state of our application. But, what about actually performing the HTTP request to load our user. This is where effects come into play.
An effect listens for actions that are dispatched, and performs some side effect, usuaully an asynchronous request. The benefit to using effects is that it enables us to isolate our async requests outside of our components, making our components less complex. Now, our components just dispatch actions and listen for values to be emitted from the store when our state changes.
NgRx is the Redux inspired State management library for Angular. It uses RxJs and Reactive programming style to provide more robust development experience.
Their core idea is simple —We can’t mutate the application state. A state is immutable. State mutation can only be done by dispatching Actions. Only pure Reducer functions are capable of changing Application State. So We get more preciseness and control over our Application State. Debugging becomes much friendlier. By restricting the ways the state can be changed, It will reduce the chances bugs can appear.
We are going to create a very basic Todo App to demonstrate the basic structure of an NgRx app. Let’s get started.
ng new todoapp-angular-ngrx --style=scss to create the basic Angular App.
npm install --save @ngrx/store @ngrx/effects to install NgRx Store and Effects in the application.
The official NgRx example app contains a different directory structure than the CLI recommended one. I’ll try to maintain the CLI structure here. It will be a familiar to the developers.
We need to create the Todo Model.
We’ve also created a static function that will return us a Mock Todo when we need it.
We now create a some state models in todo.state.ts file.
I’ve thrown in bunch of state properties that we probably won’t need for this example. Later We can add states any time to work with the reducer functions.
First we need to create actions. Actions define the changes of the Data.
Inside the src/app directory create a folder store — inside that a folder todo. Create a file todo.action.ts there.
At first, we are creating the string const variables like this — export const GET_TODO = ‘[Todo] GET_TODO’ . We are exporting this const, because we will need these in the reducer and effects later. We will use this const string to define the type of the actions.
Action classes are created with the readonly type property. Here we create constructors for the Actions that will define the changes to the state. Right now the GET_TODO actions are not used in this example app, only the GET_TODOS actions will be used.
Now we need to create the reducer functions that will take the state and action and will return a new state. It can take the payload of the action and can commit change in the new state.
The TodoListState is the main state of the app. It contains the todosListState array and loading and pending properties.
We will define a defaultTodoStates that will take the Mock Todo Model and Todo State to return a TodoState default instance.
And the defaultState is the state that the reducer function takes by default. And this reducer function contains the switch statement which will filter out the dispatched actions and will return the new state.
This is the first case. If the type of the action is GET_TODOS it will return a new state that has loading property true. This action doesn’t handle the returned state from the Server. This action just returns the default state at first call.
In NgRx, to listen for these actions and execute new actions based on them — is handled by effects.
To use effects you need to install npm install –save @ngrx/effects and provide them in the Module.
This is the TodoEffects Class. It will contain all the necessary side effects.
This is the first side effect. If an action of Type GetTodo is dispatched this sideffect GeTodo$ will be executed. It first send a Get request to get the todo list with Pagination data. If the request is successful then Then this side effect parse the response into a TodoState List object and then pass that in the payload of GetTodoSuccess Action.
If an error occurs during the process an Action of type GetTodoError is dispatched. For this example we are not handling the Error Effects or actions.
We need to import the StoreModule and the EffectsModule into AppModule to use the NgRx store and effects.
Now we need to create the components needed to display the todo lists.
ng g c components/todo/todo-list To create the Todo List component.
AppState intefact has a property todos of type TodoListState which will be used for the Store to be injected into the component.
this.todoListState$ = this.store.select(state => state.todos); To select the todoListState from the Store.
Now run ng g c components/todo/todo-list-item To generate TodoListItem Component.
We change the ChangeDetectionStrategy to OnPush for better performance. Now the components Change Detection will run only when the input values will change.
Now we need to create Input and Output variables to communicate with it’s parent component.
This child component wont dispatch any actions. This is called a Dumb Component. It will only output the values to It’s parent -The TodoListComponent. Only the TodoListComponent will have the knowledge of the store and will dispatch actions.
This is the Todo List Item. We will add class to the list item based on the state of the specific Todo.
This is the accompanying SCSS file.
If the Todo is being edited or created, we will show different controls.
These are the buttons that will emit different events like Edit, Complete and Delete.
And these are the methods that emits these values to the parent component.
We now catch the output events in the TodoListComponent. We will now dispatch the Actions from there.
Here we’ve used the Actions that we are going to create now. Important portion of this action construction is that for every kind of Action there are two extra *success and *error Actions for handling backend response.
This is the full Todo Actions file.
Todo Action Reducer
Here we are using the … spread operator of ES6 to spread the state object. Here the state object is expanded and the later properties will overwrite the previous ones.
Then in the todos array we find the created todo and then set the loading property to be true.
Get Todos Action
These are the actions for getting Todo List.
Delete Todo Action
Here we splice the todo from the todos array when the action is first dispatched. If It’s successful nothing is done, But If it’s an error then, The todo will be appended to the list again.
Update Todo Action
The first Update Action will only set the loading property to be true. After the Update Todo Effects handles the server request and then dispatches the UpdateTodoSuccess Action the loading is set to false.
So for a brief amount of time, the loading class will be activated in the todo list item.
For modifying the todoState inside the todoListState, this modifyTodoState function was separated from the main reducer function.
Complete Todo Action
And the last action will set the status of the Todo to be “done”. But the great thing is that we re use the update success and error Actions for the total state management for the action.
And Bang on !!