Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Redux with angular 2 - workshop 2016

1.759 Aufrufe

Veröffentlicht am

Slides for the 2016 Redux & Angular workshop. Redux is a popular library for state management. This workshop is about understanding how to use Redux and how to integrate it wit Angular 2

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

Redux with angular 2 - workshop 2016

  1. 1. REDUX & ANGULAR 2.0 Nir Kaufman
  2. 2. Nir Kaufman Head of Angular Development @ 500Tech - AngularJS evangelist - International speaker - Guitar player *Photoshop
  3. 3. THE CHALLENGE
  4. 4. SPA BECOME INCREASINGLY COMPLICATED
  5. 5. THERE IS NOTHING WRONG WITH THE MVC PATTERN
  6. 6. IF YOU ARE BUILDING A CRUD APPLICATION
  7. 7. BUT WE ARE PUSHING THE ENVELOPE AS MUCH AS WE CAN
  8. 8. MANAGING AN EVER-CHANGING STATE IS A HARD TASK
  9. 9. EVERYTHING IS CONNECTED TO EVERYTHING
  10. 10. VIEW
  11. 11. VIEW CONTROLLER
  12. 12. VIEW CONTROLLER MODEL MODEL
  13. 13. VIEW CONTROLLER MODEL MODEL MODEL
  14. 14. VIEW CONTROLLER MODEL MODEL MODEL MODEL
  15. 15. VIEW CONTROLLER MODEL MODEL MODEL MODEL MODEL
  16. 16. VIEW CONTROLLER MODEL LIBRARY MODEL MODEL MODEL MODEL MODEL
  17. 17. VIEW CONTROLLER MODEL LIBRARYLIBRARY MODEL MODEL MODEL MODEL MODEL MODEL MODEL
  18. 18. CHANGING SOMETHING BREAKS SOMETHING SOMEWHERE
  19. 19. ENTER REDUX
  20. 20. https://github.com/nirkaufman/redux-playground http://tinyurl.com/hq23lsa PLAY ALONG
  21. 21. REDUX IS A LIBRARY FOR IMPLEMNETING A DESIGN PATTERN
  22. 22. REDUX ATTEMPTS TO MAKE STATE MUTATIONS PREDICTABLE
  23. 23. INSPIRED BY FLUX, CQRS & EVENT SOURCING
  24. 24. REDUX INTREDUCE THREE PRINCIPLES
  25. 25. SINGLE SOURCE OF TRUTH the state of your whole application is stored in an object tree within a single store
  26. 26. THE TRUTH IS OUT THERE
  27. 27. class SideBarComponent {
 
 private visible: boolean;
 
 toggle(){
 this.visible = !this.visible
 }
 } Stateful components
  28. 28. class TabsComponent {
 
 private activeTab:Tab;
 
 activateTab(tab) {
 this.activeTab = tab;
 }
 } Stateful components
  29. 29. class Accounts {
 
 private accounts: Account[];
 
 getAccounts() {
 return this.accounts;
 }
 } Data Models
  30. 30. const state = {
 tabs: [],
 accounts: [],
 sidebar: {}
 }; Application state
  31. 31. app state STOREUI stateless UI
  32. 32. THE STATE IS READ ONLY the only way to mutate the state is to emit an action, an object describing what happened
  33. 33. class Store {
 
 private state: Object;
 
 getState(){
 return this.state;
 } 
 } Read-only State
  34. 34. STOREUI STATEgetState()
  35. 35. STOREUI STATEgetState() ACTIONdispatch(action)
  36. 36. PURE FUNCTIONS to specify how the state tree is transformed by actions, you write pure functions.
  37. 37. PURE FUNCTION return value is only determined by its input values, without observable side effects.
  38. 38. PURE FUNCTION Current State Action Next State Calculate the next state
  39. 39. PURE FUNCTION Current State Action Next State Reducer Calculate the next state
  40. 40. Uni directional data flow UI STOREactions state
  41. 41. ENTER THE STORE
  42. 42. THE STORE IS THE HEART OF REDUX
  43. 43. TO CREATE A STORE WE NEED A REDUCER
  44. 44. import { createStore } from 'redux';
 
 const store = createStore(reducer);
  45. 45. import { createStore } from 'redux';
 
 const store = createStore(reducer);
  46. 46. REDUCE METHOD applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
  47. 47. function sum (previousVal, currentVal) {
 return previousVal + currentVal;
 }
 
 [0, 1, 2, 3, 4].reduce(sum); // => 10 Reduce in action
  48. 48. EVENT SOURCING capture all changes to an application state as a sequence of events.
  49. 49. function counter (state, action) {
 switch (action) {
 case 'up':
 return state + 1;
 case 'down':
 return state - 1;
 default:
 return state;
 }
 }
 
 ['up', 'up', 'down'].reduce( counter, 0 ); Simple counter app
  50. 50. THE REDUCER RETURNS THE NEXT STATE BASED ON A SEQUENCE OF ACTIONS
  51. 51. THE SAME SEQUENCE OF ACTIONS WILL PRODUCE THE SAME STATE
  52. 52. PREDICTABLE STATE CONTAINER
  53. 53. HANDS ON! implementing a working store in less then 30 lines of code.
  54. 54. function createStore(reducer) {
 let state = null;
 const listeners = [];
 
 function getState() {
 return state;
 }
 
 function dispatch(action) {
 state = reducer(state, action);
 listeners.forEach( listener => listener() )
 }
 
 function subscribe(listener) {
 listeners.push(listener);
 return function unsubscribe() {
 let index = listeners.indexOf(listener);
 listeners.splice(index, 1)
 }
 }
 
 return { getState, dispatch, subscribe }
 }
  55. 55. STORE API dispatch(action) subscribe(listener) getState() replaceReducer(reducer)
  56. 56. ASYNC DATA FLOW
  57. 57. MIDDLEWARE extension point between dispatching an action, and the moment it reaches the reducer.
  58. 58. Async flow with middlewares UI STOREaction state
  59. 59. Async flow with middlewares UI STORE state MIDDLEWARE action action
  60. 60. export const middleware = store => next => action => {
 return next(action)
 }; Middleware - get the current state from the store - pass an action to the next middleware - access the provided action
  61. 61. ANGULAR & REDUX
  62. 62. ANGULAR IS A NEW PLATFORM FOR BUILDING COMPLEX MODERN SPA’S
  63. 63. https://github.com/nirkaufman/angular2-redux-workshop.git http://tinyurl.com/h4bqmut GET THE CODE
  64. 64. git checkout master
  65. 65. AN ANGULAR APP IS A TREE OF COMPONENTS
  66. 66. WE MAP PROPERTIES TO THE STATE
  67. 67. WE DISPATCH ACTIONS IN REACTION TO EVENTS
  68. 68. COMPONENT COMPONENT STORE [properties](events) actions state
  69. 69. git checkout 01_project-structure
  70. 70. ANGULAR 2.0 ENCOURAGING AN OOP APPROACH
  71. 71. TO USE DEPENDENCY INJECTIONS WITH REDUX WE WRAP STUFF IN PROVIDERS
  72. 72. import {createStore} from “redux"; import {RootReducer} from './reducers/root'; 
 export class Store {
 
 private store = createStore(rootReducer);
 
 get state() {
 return this.store.getState();
 }
 
 dispatch(action){
 this.store.dispatch(action)
 }
 }
  73. 73. WE COMBINE MULTIPLY REDUCERS TO ONE ROOT REDUCER
  74. 74. import {combineReducers} from 'redux';
 
 export const RootReducer = combineReducers({
 app: (state = 0) => state
 }); combineReducers in action
  75. 75. WE NEED TO REGISTER OUR STORE PROVIDER ON THE MODULE
  76. 76. @NgModule({
 declarations: [AppComponent],
 imports : [BrowserModule, HttpModule],
 providers : [Store],
 bootstrap : [AppComponent]
 })
  77. 77. NOW WE CAN INJECT IT TO OUR COMPONENT AND GET THE STATE!
  78. 78. export class AppComponent {
 
 constructor(store: Store) {
 console.log(store.state);
 }
 }
  79. 79. git checkout 02_wiring
  80. 80. COMMON SCENARIOS
  81. 81. REQUIREMENTS CRUD operations Authentication Notifications Persistance View modes Logging
  82. 82. @Injectable()
 export class ListActions {
 
 private store:Store;
 
 constructor(_store:Store) {
 this.store = _store;
 }
 
 add(item) {
 this.store.dispatch({
 type : LIST.ADD_ITEM,
 payload: item
 })
 }
 
 remove(item) {
 this.store.dispatch({
 type : LIST.REMOVE_ITEM,
 payload: item
 })
 }
 } The list actions class is an helper for dispatching actions to the store
  83. 83. git checkout 03_crud
  84. 84. @Injectable()
 export class Auth {
 private http:Http;
 private URL:string;
 
 constructor(_http:Http) {
 this.http = _http;
 this.URL = 'http://localhost:4000/api/login';
 }
 
 middleware = store => next => action => {
 
 if (action.type !== USER.LOGIN) {
 return next(action) 
 } else if (action.type === USER.LOGIN) {
 
 const successHandler = result => next({
 type : USER.LOGIN_SUCCESS,
 payload: result.json()
 });
 
 const errorHandler = error => next({
 type : USER.LOGIN_FAILED,
 payload: error.json()
 });
 
 this.http.post(this.URL, action.payload)
 .subscribe(successHandler, errorHandler);
 
 return next({type: APP.LOADING})
 }
 }
 } By wrapping the middleware in provider we can use angular services such as Http
  85. 85. git checkout 04_authentication
  86. 86. const initialState = {
 loading: false
 };
 
 export function appReducer(state = initialState, action) {
 
 switch (action.type) {
 case APP.LOADING:
 return Object.assign({}, state, {loading: true});
 
 case APP.READY:
 case USER.LOGIN_SUCCESS:
 return Object.assign({}, state, {loading: false});
 
 default:
 return state;
 }
 } ‘application level’ reducer can handle
  87. 87. git checkout 05_spinner
  88. 88. GET READY FOR TIME TRAVEL DEBUGGING
  89. 89. class Model {
 
 private items = [];
 
 
 addItem(item) {}
 
 updateIten(item) {...}
 
 removeItem(item) {...}
 
 } separation of state from mutation methods
  90. 90. class ModelCrud {
 
 static addItem(model, item) {…}
 
 static updateIten(model, item) {…}
 
 static removeItem(model, item) {…}
 
 } separation of state from mutation methods const Model = {
 items: []
 };
  91. 91. git checkout 06_debugger
  92. 92. NEXT STEPS
  93. 93. Angular & Redux Workshop https://leanpub.com/redux-book THE COMPLETE REDUX BOOK
  94. 94. Angular & Redux Workshop RESOURCES REDUX http://redux.js.org/ https://egghead.io/series/getting-started-with-redux CQRS & EVENT SOURCING https://msdn.microsoft.com/en-us/library/dn568103.aspx https://msdn.microsoft.com/en-us/library/dn589792.aspx ANGULAR 2 angular-2-change-detection-explained.html https://github.com/ngrx/store https://github.com/angular-redux/ng2-redux
  95. 95. NIR KAUFMAN nir@500tech.com Head of Angular Development @ 500Tech @nirkaufman github.com/nirkaufman meetup.com/Angular-AfterHours/ keep in touch!

×