a site for tech enthusiast

Redux Introduction

Redux is a javascript library to store and manage application state in single state tree and share it across components or objects in a very efficient way. Most of javascript developers use redux in ReactJS application, but actually redux is an independent library so we can use it with any others javascript framework.

But why redux ? what problems are redux solving ? Let’s imagine that in a highly asynchronous environment we have several buttons (let say over than 20) in our page, each one of them leads to a change of 5 or 6 properties in our app, how do we know which states we are in ? we could lost in the middle of nowhere and have no idea what bugs will we find. Redux helps us to predict the next state and remember the previous states (a.k.a time machine).

Redux in Angular 2

Angular 2 armed with a powerful procedure to handle data flow between parent and child component by declaring @input decorator within child component to receive data from parent and declaring @output as event emitter in child component for sending data to parent.

In the case above we see that our parent component has one child component, we can figure the communication between components as below:

Angular 2 Component Interaction

For small kind of application which has a very little of interaction between components there wouldn’t be a problem, but when the application getting bigger and involved so many interactions, managing the state component per component as showing above will be very hard.

Now let’s go to the step-by-step how to use redux within our angular application:

Install redux from npm

1

npm install redux--save

Create actions

src/app/actions/app.action.ts

JavaScript

1

2

3

4

5

6

7

8

9

10

export constADD_TODO='ADD_TODO';

exportdefaultclassAppAction{

addTodo(text){

return{

type:ADD_TODO,

text

}

}

}

Create reducers

src/app/reducers/app.reducer.ts

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

import{ADD_TODO}from'../actions/app.action';

// Define empty object as initial state

constinitialState=[];

export defaultfunctiontodoApp(state:any=initialState,action:any){

switch(action.type){

case ADD_TODO:

return[

...state,

{

text:action.text,

completed:false

}

];

default:

returnstate

}

}

Create Store

src/app/app.store.ts

JavaScript

1

2

3

4

5

import{createStore}from'redux';

import todoApp from'./reducers/app.reducer';

constAppStore=createStore(todoApp);

export defaultAppStore;

In parent component, subscribe to listen on every state changes

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

import{Component,Inject}from'@angular/core';

import AppStore from'./app.store';

import AppAction from'./actions/app.action';

constAPP_STORE=AppStore;

@Component({

selector:'app-root',

providers:[

{provide:APP_STORE,useValue:AppStore},

AppAction

],

template:`

<ul>

<li*ngFor="let stateItem of state">{{stateItem.text}}</li>

</ul>

<app-child></app-child>

`

})

exportclassAppComponent{

state:any;

subscribe:any;

constructor(

@Inject(APP_STORE)privateappStore,

private appAction:AppAction

){

// Current state is empty

this.state=this.appStore.getState();

// Subscribe to listen on every state changes

this.subscribe=this.appStore.subscribe(()=>{

this.state=this.appStore.getState();

});

}

}

Update state in child component (no more event emitter)

src/app/child.component.ts

JavaScript

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

import{Component,Inject}from'@angular/core';

import AppStore from'./app.store';

import AppAction from'./actions/app.action';

constAPP_STORE=AppStore;

@Component({

selector:'app-child',

providers:[

{provide:APP_STORE,useValue:AppStore},

AppAction

],

template:`

<input type="text"name="todoInput"[(ngModel)]="todoInput"/>

<button(click)="addNew()">Add NewTodo</button>

`

})

exportclassChildComponent{

todoInput:string;

constructor(

@Inject(APP_STORE)privateappStore,

private appAction:AppAction

){}

addNew():void{

this.appStore.dispatch(this.appAction.addTodo(this.todoInput));

}

}

Our angular code above will given the following result:

Now we are using redux and it’s change the way our component communicate each other:

Angular 2 + Redux Component Interaction

Conclusion

Redux offers really great features in order to develop such a complex web application, with a single source of truth (a.k.a store) it would be easier to maintain the application state. It also offers a clean way to map properties in the data store with properties declared in application’s model every time the store changes state. One last thing, with the mighty time-machine, some functionality which has been traditionally difficult to implement – Undo/Redo, for example – can suddenly become trivial to implement.