Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Managing State In Angular with Redux

Managing State In Angular with Redux

Passing state between child and parent components can be cumbersome in larger Angular projects. Using Redux in these projects can greatly simplify state management, but we have to get past the initial learning curve. In this presentation we will look at the pattern Redux follows, discuss Reducers, Action Creators and State. We will examine Redux's use of the pub/sub pattern and reliance on immutability.

Doug Corbett

January 11, 2018
Tweet

More Decks by Doug Corbett

Other Decks in Programming

Transcript

  1. Basic State Management in Angular 1 Anatomy of a Redux

    Implementation 3 Final Thoughts 4 Basic Redux Ideas 2 Agenda
  2. Singleton Services authService currentUser firstName lastName permissions isAdmin browsingHistory orderService

    orderList productList currentOrders productList cartService productList currentItem productService productList currentProduct featuredProducts trendingProducts bestSellingToys moviesOnSale bestSellingBooks reccomendedProducts
  3. Singleton Services pmtMethodService pmtMethodList defaultMethod featuredProducts trendingProducts bestSellingToys moviesOnSale bestSellingBooks

    reccomendedProducts membershipService profileService messagingService rentalService deviceMgmtService videoService authService currentUser firstName lastName permissions isAdmin browsingHistory orderService orderList productList currentOrders productList cartService productList currentItem productService productList currentProduct featuredProducts trendingProducts bestSellingToys moviesOnSale bestSellingBooks reccomendedProducts
  4. Redux • Data Architecture Pattern • Characteristics • Centralized State

    Management • Immutability • Pub/Sub communication between State Store and listening components
  5. Why? • More complex apps become easier to work with

    using centralized state. • Property binding between parent and child components can run into problems with larger applications. • Hard to get a picture of the entire application’s state without centralized state. • Developers have one place to look for state instead of components and services. • Undo/Redo • Testability
  6. Centralized State Management • Can view the state of the

    entire application easily • Changes to state happen in one place • Changes to the state can be subscribed to and unsubscribed from so dependent component can react to state changes efficiently.
  7. Immutability • The practice of not modifying values in memory

    directly, but creating new values in memory and changing a variable to point to the new location. • Avoid side effects • Fast • Makes multi threaded apps safer by avoiding locking and race conditions • Increased Garbage Collector processing and memory usage
  8. State • An interface that represents the structure of the

    state of the application that needs to be available to the entire application. export interface AppState { currentUser: UserProfile, recentlyViewedProducts: Array<Product>, cart: Array<Product> }
  9. Action • Objects that represent some kind of action in

    the system. It is comprised of two parts, an action identifier and, optionally, a payload. { type: ‘ADD_PRODUCT_TO_CART’, product: { “title’: “Girls bicycle”, “description”: “Two wheels and ribbons”, “quantity”: 100 } }
  10. Reducer • A reducer takes an action and the old

    state and returns a new state. • It does not change state directly. • It is a “pure function”, meaning that based on the same input, it returns the same output without side effect. import { ADD_PRODUCT_TO_CART } from ‘./cart.actions’ const initialState: AppState = { cart: [] } export const cartReducer: Reducer<AppState> = (state: AppState = initialState, action: Action): AppState => { switch(action.type) { case ‘ADD_PRODUCT_TO_CART’: return { Object.assign({}, state, { cart: state.cart.concat( (<AddProductAction>action).product; ) } } default: return state; } }
  11. Redux Elements • Action • Reducer • State • Store

    • Component Reducer Action Component Action (string) Data (object) Store State
  12. Triggering Components • These are the components that intend to

    indirectly change state. They do this by dispatching an Action Object to the Store. store.dispatch({ type: ‘ADD_PRODUCT_TO_CART’, product: { “title’: “Girls bicycle”, “description”: “Two wheels and ribbons”, “quantity”: 100 } } as AddProductAction);
  13. Store • Object responsible for persisting and changing state. //

    app.store.ts let store: Store<AppState> == createStore<AppState>(cartReducer); export const AppStore = new InjectionToken(‘App.store’); const devtools: StoreEnhancer<AppState> = window[‘devToolsExtension’] ? window[‘devToolsExtension’]() : f => f; … export createAppStore(): Store<AppState> { return createStore<AppState>( reducer, compose(devtools) ); } export const appStoreProviders = [ { provide: AppStore, useFactory: createAppStore } ];
  14. Redux Elements • Action • Reducer • State • Store

    • Component • Action Creator • Observer Reducer Component Store State Action Creator Action Action (string) Data (object) Observer
  15. Action Creators • This is an optional convenience helper object

    that takes a payload and creates an action class with an internally specified action and provided payload. • This is not specifically required, but leverages strong typing to eliminate typing defects and improves code readability. // cart.actions.ts import { Action, ActionCreator } from ‘redux’ export const ADD_PRODUCT_TO_CART: string ‘ADD_PRODUCT_TO_CART’; export const addProductToCart: ActionCreator<Action> = (product) => ( { type: ADD_PRODUCT_TO_CART, product: product } );
  16. Observers • Any component that subscribes to state changes constructor(@Inject(AppStore)

    private store: Store<AppState>) { store.subscribe(() => this.updateState()); this.updateState(); } updateState() { // getUnreadMessagesCount is a selector function this.unreadMessagesCount = getUnreadMessagesCount(this.store.getState()); }
  17. Other Concepts • rootReducer – every app has one starting

    reducer and it may possibly have sub reducers below that. • State Slices – a way of grouping related reducers, actions and state away from those unrelated.
  18. Final Thoughts • The Redux pattern takes some getting used

    to. • Redux is designed to make things easier for large projects but at a cost. • Redux emerged out of the React ecosystem and you are likely to encounter it. • Once you internalize the pattern, it simplifies the burden of managing state
  19. Reference Materials Official Angular Documentation https://angular.io Build Enterprise Applications with

    Angular 2 (and Angular 4) – Mosh Hamedani https://www.udemy.com/angular2-advanced Using Redux to Manage State in Angular - Hendrik Swanepoel https://app.pluralsight.com/library/courses/angular-2-redux-manage-state Advanced Redux - Daniel Stern https://app.pluralsight.com/library/courses/advanced-redux Building a Redux application with Angular 2 – Parts 1 and 2 - Hristo Georgiev https://www.pluralsight.com/guides/front-end-javascript/building-a-redux-application-with-angular-2-part-1 https://www.pluralsight.com/guides/front-end-javascript/building-a-redux-application-with-angular-2-part-2 ng-book – The Complete Book on Angular 4 – Nathan Murray and Ari Lerner Angular Redux Demo code https://github.com/dougcorbett/angular-redux-demo