SlideShare a Scribd company logo
Redux Data Flow with Angular
Gil Fink
sparXys CEO
@gilfink / www.gilfink.net
SPAs Are Complex
Service
Component
Service
ComponentComponent
Service
Component
Service
ComponentComponent
Component
Component
Service
Service Component
Service
Service
Component
Service
ComponentComponent
Component
Component
Service
Service Component
Service
Service
Component
Service
ComponentComponent
Component
Component
Service
Service Component
Service
Service
Component
Service
ComponentComponent
Component
Component
Service
Service Component
Service
Then you make a small change…
Redux data flow with angular
About Me
• sparXys CEO and senior consultant
• Microsoft MVP in the last 8 years
• Pro Single Page Application Development (Apress) co-author
• 4 Microsoft Official Courses (MOCs) co-author
• GDG Rishon and AngularUP co-organizer
Agenda
• The Redux pattern
• Combining Redux and Angular
• ng2-redux library in a nutshell
Known SPA Complexity Solutions
• Command Query Responsibility Segregation (CQRS)
• Event Sourcing
• Flux
• And more
Redux
• Design pattern based on Flux
• But it’s not Flux!
• Predictable state container for JavaScript apps
Redux Principles
1. Single source of truth
Single Source of Truth
• The application state is stored in an object tree within a single store
let state = store.getState();
Redux Principles
1. Single source of truth
2. State is read-only
State is Read-Only
• The only way to mutate the state is to emit an action describing what
happened
store.dispatch({
type: 'ADD_GROCERY_ITEM',
item: { productToBuy: 'Milk' }
});
store.dispatch({
type: 'REMOVE_GROCERY_ITEM',
index: 3
});
Redux Principles
1. Single source of truth
2. State is read-only
3. Changes are made with pure functions
Changes Are Made with Pure Functions
• To specify how the state is transformed by actions, you write a pure
function
function groceryItemReducer(state, action) {
switch (action.type) {
case 'ADD_GROCERY_ITEM':
return object.assign({}, state, {
groceryItems: [
action.item,
…state.groceryItems
]
};
default:
return state;
}
}
Let’s drill down
Redux Actors
Action
Creators
View
ReducersStore
Actions
• Plain JavaScript objects
• Include
• Type – action type
• Payload – the change that should occur
let action = {
type: 'ADD_GROCERY_ITEM',
item: { productToBuy: 'Milk' }
};
Action
Creators
Action Creators
• Functions that return actions
const ADD_GROCERY_ITEM = 'ADD_GROCERY_ITEM';
function addGroceryItem(item) {
return {
type: ADD_GROCERY_ITEM,
item: item
};
}
Action
Creators
Reducers
• Change the state in response to things that happened in the
application
• Pure functions
function groceryItemReducer(state, action) {
switch (action.type) {
case ADD_GROCERY_ITEM:
return object.assign({}, state, {
groceryItems: [
action.item,
…state.groceryItems
]
};
default:
return state;
}
}
Reducers
Store
• Only one store object
• Store data accessed through getState function
• Updates only in response to dispatching an action
import {createStore} from ‘redux’;
import {groceryItemReducer} from ‘./reducers/groceryItemReducer’;
const store = createStore(groceryItemReducer);
Store
Redux Data Flow
Action
Creators
View
ReducersStore
interaction (click, mouse etc.)
dispatch(action) (previous state, action)
(new state)
(current state)
Redux Data Flow – Cont.
Action
Creators
View
ReducersStore
interaction (click, mouse etc.)
dispatch(action) (previous state, action)
(new state)
(current state)
Outside Action
(push, Ajax callback
and etc.)
Redux Library API
• Redux is a small and compact library:
• createStore(reducer)
• combineReducers(reducers)
• applyMiddleware(middlewares)
• compose(functions)
• bindActionCreators(creators, dispatch)
• Store API:
• store.dispatch(action)
• store.getState()
• store.subscribe(listener)
Demo: Redux in action
Redux Middleware
• Extension point between dispatching an action and the reducer
• Middleware examples:
• Logging
• Async operations
• Routing
const middleware = store => next => action => {
// do something before dispatcher
let result = next(action);
// do something after dispatcher
return result;
}
const store = createStore(reducer, applyMiddleware(middleware));
Demo: Redux Middleware
What about Angular?
Angular and Redux
• Redux can be applied in Angular oriented applications
• It’s a data flow pattern
• Popular Angular & Redux libraries:
• ng2-redux
• ngrx/store
ng2-redux
https://github.com/angular-redux/ng2-redux
npm install --save ng2-redux
ng2-redux - Setup
• Add the module
• Create the store and provide it in the main module
import { NgReduxModule, NgRedux } from 'ng2-redux';
@NgModule({
imports: [ /* ... */, NgReduxModule ]
})
class AppModule {
constructor(ngRedux: NgRedux<IAppState>) {
ngRedux.provideStore(store);
}
}
ng2-redux - Usage
• Use the @select decorator and dispatch function:
class App {
@select() counter: Observable<number>;
constructor(private ngRedux: NgRedux<IAppState>) {}
increment() {
this.ngRedux.dispatch({ type: INCREMENT});
}
}
Demo: Redux + Angular
Questions?
Summary
• Redux
• Is a data flow design pattern
• Reduces complexity when building big SPAs
• Can be applied in Angular apps
Resources
• Redux:
https://github.com/reactjs/redux
• ng2-redux:
https://github.com/angular-redux/ng2-redux
• ngrx/store:
https://github.com/ngrx/store
• My Blog – http://www.gilfink.net
• Follow me on Twitter – @gilfink
Thank You!

More Related Content

Redux data flow with angular