Introduction
We have seen a lot of problems sending data between Angular component hierarchy. Redux is the best solution to flow the data between the components. So that whenever any component changes the data, it will reflect on each component that is using/subscribing to that data. Here, I will suggest how to implement Redux in an existing or new Angular application. We will follow the manual approach without any library like ng-redux2
, etc.
Note: I'm expecting you already have a knowledge of Angular and typescript because I'm using both in this article.
Background
Redux is an open-source JavaScript library for managing application state. It totally depends upon you whether you want to use redux in your application or not. You can even create Angular application without using redux but it will be very difficult to manage application state when we create a big application.
Using the Code
Here, we will install the redux into our application, then use the action, reducers and store to perform unidirectional data flow.
Installation of Redux
Use the below to install redux in your Angular application.
npm install redux --save
To implement redux, you must be aware of three things, that are Store, Reducers and Actions.
- Store: Store maintains or provides the application state.
- Reducers: Reducers are used to create new state.
- Actions: Actions are payloads of information that send data from your application to your store. They are the only source of information for the store. You send them to the store using
store.dispatch()
.
Data Flow
Scenario
Suppose you are having Angular application where you are displaying comments. I have created Angular application using fake json web API. You can see the data using the below URL.
https://jsonplaceholder.typicode.com/comments
You can get the Angular application code from my gitHub repository. The link is mentioned at the end of the article. It's a crud application.
Model
export class CommentsModel {
public postId: number;
public id: number;
public name: string;
public email: string;
public body: string;
}
State Interface
We are creating interface to let redux store know which type of application state we are going to store. Later, we will use this interface to create the redux store.
In the below code, we are importing the comment model. The object property in interface holds the array of the above mentioned model. It means our redux store will hold the array of comment model.
import { CommentsModel } from "../Model/Comment.Model";
export interface IAppState {
object: CommentsModel[],
}
Actions
Actions can be triggered by Angular components to update the state of the object. Every action must have type property which will be used by reducer to understand for which acton it has to create new state. Here, we are using commentsModel
as an application state for the application.
In the below code, AddComments
is the action which will be triggered by Angular component. It will return the new state in the object property of action.
export function AddComments(commentObject) {
return {
type: "Add",
object: commentObject
}
}
Reducers
Reducers are used to create the new application state.
In the code below, we are importing our interface that is IAppState
because it tells state of our application.
In the second line, we are initialising the default state of the application. We have assigned empty state to the application by default as we are assigning object :[] to empty array.
In the third line, you are seeing a function which will be used to perform action based on action type that we are going to perform. Every reducer function will take two arguments that are state and action. As of now, we have implemented only Add but we can have update, delete, etc. We are using switch here but you can use if and anything else you prefer. Switch case is based on the action type here we are using for case "Add".
Inside Add case, we are creating new state for the application using object.assign
. The object.assign
method creates a new state instead of overriding the existing state.
import { IAppState } from "./IAppState";
const initialState: IAppState = {
object: []
};
export function UniformDataFlowReducer(state = initialState, action) {
switch (action.type) {
case "Add":
return AddNewObject(state, action);
}
}
function AddNewObject(state, action) {
return Object.assign({}, state, {
object: action.object
})
}
Store
This is how you can create a redux store. To create a store, you must need reducer. I have already created a reducer to update the state and send new state whenever some new comments have been added to the application. The reducer name is UniformDataFlowReducer
. We have created a store of type IAppState
. Here, IAppState
is application state interface.
import {createStore} from "redux";
import {CommentsModel} from "../Model/Comment.Model";
import {UniformDataFlowReducer} from "./CommentsReducer.Redux";
import {IAppState} from "./IAppState";
export const commentStore = createStore<IAppState>(UniformDataFlowReducer);
Dispatch
The store dispatch method is used to update or create the new state in the store. The dispatch
method of store will be triggered by Angular component only. It will pass the new object to the store which will act as new state for the application.
Here, commentStore
is the redux store and this line of code will be called inside add comment method of Angular component. We will pass the Angular form data to the method and it will add the new comment model object inside existing model array. The model array in the below code is stored inside service member, i.e., this.dataService.list
.
Here, AddComments
is the action we already discussed above.
commentStore.dispatch(AddComments(this.dataService.list));
GetState
All comments that depend upon the comment model array will subscribe to redux store state. So whenever there is any change in the current application state, then every component will get to know about it and render the result accordingly. We can get the state as below:
this.dataService.list=commentStore.getState().object;
Here, this.dataservice.list
is the comment model array used to display result on Angular component template. We are calling store.getState
and extracting the current state object from the store.
Download the angular Crud application from my github repository mentioned below:
Try to include redux in the above application, change the localstorage
with redux store. Let me know in case you have any further query on redux library. Add the redux store reducer and Actions shown below in image.
I hope you will like the article. :)