1 of 29

Redux, with AngularJS 1.x

2 of 29

Agenda

Our Frontend Background / Tech. Stack

Why use redux?

Libraries helping us

Data flow / Impl

Problem(s) we still fighting for?

3 of 29

Background / Tech. Stack

Revamping for multifunctional / large scale app

From Multi-Page App to single page app

AngularJS 1.5.x

Redux

ImmutableJS

4 of 29

Motivation of using Redux

For large scale SPA

Complex UI lead to display differently the same data

Some data can be simultaneously edited

Sharing same data across multiple components

5 of 29

Why not Flux

We Tried!

Complex stores

We need writing a bunch of stores

Lack of good angular Implementation

6 of 29

Why not Flux

Vs Redux

Support middleware for customized checking

Just one store, Just write your reducer

Provided a bunch of functionality:

Undo/Redo, Logging, Promise handling…..

7 of 29

Libraries

ng-redux

https://github.com/wbuchwalter/ng-redux

Wrapper of official redux

Support many redux middlewares

Handled angular digest loop

8 of 29

Libraries

Async handling : redux-thunk / redux-promise

Logging : redux-logging

Immutable store : redux-immutable

ui-router helper : redux-ui-router

9 of 29

Data flow with angular

Store

Action Creator

View

Reducer

dispatch

Middlewares

manipulate

ng controller

ng directive

ng component

immutableJS

ng service

mixins

mixins

mixins

mixins

ng service

ng service

ng service

mixins

mixins

mixins

mixins

action

10 of 29

Demo Example

2 Component sharing same state but present in different ways

Need single point of truth

11 of 29

Angular initialization

Include module `ngRedux`

Combine all reducers

Setup middlewares

$ngReduxProvoider.create()

12 of 29

Combine-Reducer

For complex and multi modules app

Impossible to place all reducing function in a single Reducers

It will return a single object holding each reducers together

13 of 29

!!! ImmutableJS w/ Combine-Reducer

Without Combine-Reducer. It is ok

store = Immutable.Map( )

With Combine-Reducer. It will...

store = { hi : true } //plain js object

14 of 29

!!! ImmutableJS w/ Combine-Reducer

15 of 29

Reducer Implementation

As Simple JS mixins, no more.

Don’t mutate the state

Must handle the state for unknown action.

Especially for applied Combine Reducer, the first time call of reducer become initial state

Reducer

mixins

mixins

mixins

mixins

16 of 29

Action Creator Implementation

As angular service

Following Flux Standard Action

Don’t dispatch the action inside

Action Creator

ng service

ng service

ng service

ng service

17 of 29

Views Implementation

All redux store’s method are exposed by $ngRedux

$ngRedux.getState()

$ngRedux.subscribe()

$ngRedux.dispatch()

View

ng controller

ng directive

ng component

18 of 29

Views Implementation - connect

Expect a callback to be fired every time there is a change to your selectedState.

Comparison handled by shallowequal

Handled Angular $$hashkey

View

ng controller

ng directive

ng component

19 of 29

Views Implementation - connect

$ngRedux.connect (mapStateToTarget, mapDispatchToTarget) ( target )

mapStateToTarget :

What we want to map to our target

function MUST return an plain JS object and result will be merged to target

Triggered any time state update

View

ng controller

ng directive

ng component

20 of 29

Views Implementation - connect

$ngRedux.connect (mapStateToTarget, mapDispatchToTarget) ( target )

mapDispatchToTarget :

Actions we want to map to our target

Object, Optional

Tt assumed its action creator and merge all method to target

View

ng controller

ng directive

ng component

21 of 29

Views Implementation - connect

$ngRedux.connect (mapStateToTarget, mapDispatchToTarget) ( target )

target :

Optional

Object / Function

If object passed, the results of mapStateToTarget and mapDispatchToTarget will be merged onto it

If function passed, it receive the results of mapStateToTarget and mapDispatchToTarget as parameters.

View

ng controller

ng directive

ng component

22 of 29

Views Implementation - subscribe

Redux basic API

Low level then .connect

Trigger every time if state updated without any checking

View

ng controller

ng directive

ng component

23 of 29

Middlewares

Logging, Async Actions

Extension point between dispatching an action, and the moment it reaches the reducer.

Customize application validation / checking

Middlewares

mixins

mixins

mixins

mixins

24 of 29

Others!

Redux-Batch Action - batch dispatch synchronize actions

Redux-Promise - Pass promise as payload directly

25 of 29

Others!!

Redux-actions

Flux Standard Action utilities for Redux

createAction - for action creator

Good partner with redux-promise, handling promise.reject automatically

26 of 29

Others!!

Redux-actions

handleActions - for reducer

Replace switch case with object literals

Separate normal and exception handling

27 of 29

Problem(s) still fighting for

Some utilities no support ImmutableJS (eg: redux-ui-router)

Sequential async action handling (redux-thunk?)

Local state for reusable components (redux-state?)

Tediously long immutableJS selection (reselect?)

PODS based code structure caused reducer decentralization (example)

28 of 29

References

29 of 29

We’re Hiring