Tech tutorials What Redux Can Do for Your Angular 2 Application
By Insight Editor / 6 Dec 2016 , Updated on 16 May 2019 / Topics: Application development
By Insight Editor / 6 Dec 2016 , Updated on 16 May 2019 / Topics: Application development
Pairing Redux with your Angular 2 application may bring more to the table than you’ve considered. With a rich feature set and predictable application behavior, Redux adds to your application the insights and workflow you’ve been looking for.
“Redux is a predictable state container for JavaScript apps. It helps you write applications that behave consistently, run in different environments (client, server and native) and are easy to test.” (http://redux.js.org/)
This topic is broad and can’t be covered in its entirety here. However, the general idea is to save the state of your entire application in an object tree. The object tree is saved in a container object called the store. State is captured with Redux when an action is taken via an Angular component. The lifecycle pattern shown below offers predictable behavior throughout the entire application, regardless of size.
NG2 Redux state/data flow
Every change to the application state is captured as an action and sent to the store to be recorded. Capturing state changes in your application can provide the ability to review and refine many aspects of your application, from User Experience (UX) to logic efficiencies.
The application state can be used to quickly identify bottlenecks, allowing poor user interaction to be caught early in the development process. This means once your application rolls out for testing, you can spend more time on the shiny new feature set that’s suddenly become a new project requirement. Following are some examples of what Redux can offer.
As a user moves through an application that’s using Redux, we can capture router state change. This will allow us to visualize user navigation. We can identify specific workflows that could be defined in a clearer way.
New tools such as Redux VCR provide the ability to monitor/record a user session using Redux store interactions in real time. From a UX perspective, having the ability to monitor a user and watch him or her walk through complicated application interactions can be invaluable.
Example application
Above, you can see application state changes played like a movie with the use of time travel debugging. Also, note that each action taken by the user is being displayed in the console, visible in the bottom right corner.
The image above is of an application state tree displayed using the Redux debugging tool. It was used for an example Angular 2/NG2-Redux application I put together. You quickly get an overview of my example application structure without browsing through the app. My state contains only a couple of modules at this point, clients, router and session. With a couple of clicks, I can drill into different modules and see data structures and associations.
Using the Redux development tools package, you can see actions that have been performed on the application state in sequential order. When an action is dispatched, Redux captures and displays the previous application state, the action taken and the next application state.
Working your way backward or forward through the state assures your action has the correct effect on the User Interface (UI). This makes debugging a breeze, saving the developer from filling out forms thousands of times to assure the correct state transition has been a success.
What integration would look like in your Angular 2 application:
View the original GitHub Gist.
/***
* Actions Example
*
* Here you can see "addClient" method dispatching a change to the
* Reducers in order the record the new state change.
***/
@Injectable()
export class ClientActions {
constructor(
private _ngRedux: NgRedux<IAppState>,
private _client: ClientService) {}
addClient = (client) => {
return this._client.getNextClientId().then(clientId => {
return this._ngRedux.dispatch({
type: CLIENT_ADDED,
payload: {
company: client.company,
email: client.email,
active: client.active
}
});
});
};
}
/***
* Component Example
***/
/***
* The decorator "changeDetection: ChangeDetectionStrategy.OnPush"
* is used here so if the store is changed the component state will be
* automatically updated.
***/
@Component({
selector: 'client-component',
template: TEMPLATE,
changeDetection: ChangeDetectionStrategy.OnPush,
providers: [ ClientActions ] // Actions are injected as a provider.
})
export class Clients {
/***
* Build the component out using reactive form. Don't use template driven forms as they
* enable bi-directional data binding which can lead to mutability.
* Do not mix ngModel with reactive forms!
***/
/***
* @select() provides access to the data store.
***/
@select() client$: Observable<IClients>; // <-- Data flowing down from the store
// forms items
clientForm: FormGroup;
company = new FormControl('', Validators.required);
email = new FormControl('', Validators.required);
active = new FormControl('false');
/***
* We need inject actions and the state into the
* component to make them available.
*
* @param _ngRedux
* @param _clientActions
* @param _fb
***/
constructor(private _ngRedux: NgRedux<IAppState>,
private _clientActions: ClientActions,
_fb: FormBuilder) {
this.clientForm = _fb.group({
company: this.company,
email: this.email,
active: this.active
});
}
/***
* Calling an Action:
*
* The Form update is causing a state change.
* To let the store know that the state is changing we use an action.
***/
onSubmit() {
this._clientActions.addClient(this.clientForm);
}
}
If you’re building a small application, integrating Redux into your Angular 2 application might not make sense. Reasons to not use Redux are best explained by the Redux author himself, Dan Abramov.
If you’re building a large, data-intensive application, I highly recommend reviewing what Redux can bring to your application.
Here are some great resources you can use: