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

NgRx Ducks - Dynamic types facades

NgRx Ducks - Dynamic types facades

This slide deck demonstrates how NgRx Ducks helps you to write domain driven style redux applications with NgRx.

You will learn about the API of NgRx Ducks and how it seamlessly integrates with vanilla NgRx.

https://twitter.com/gregonnet

https://github.com/co-IT/ngrx-ducks

Gregor Woiwode

July 24, 2019
Tweet

More Decks by Gregor Woiwode

Other Decks in Programming

Transcript

  1. Agenda • The story behind NgRx Ducks? • Introducing the

    API • LIVE Coding • Advanced features of NgRx Ducks • LIVE Coding
  2. It is getting harder and harder to keep track of

    the decentralized infrastructure of a Redux application.
  3. Each slice is represented by... Login journey Authentication User menu

    Registration journey User details Actions Selectors Effects Reducer
  4. Actions Effects Selectors Reducer What if we can bundle NgRx’s

    building blocks dynamically having one easy to use API?
  5. API

  6. export const increaseBy = createAction( 'Increase by', props<{ payload: number

    }>() ); Action Creator The birth of a duck @Action('Increase by') increaseBy( state: number, payload: number ): number { return state + payload; } Duck Action Type Action Payload
  7. export const reducer = createReducer<number>( 0, on(increaseBy, (state, { payload

    }) => state + payload) ); Case-Reducer The birth of a duck @Action('Increase by') increaseBy( state: number, payload: number ): number { return state + payload; } Duck
  8. export class Counter { @Action('Increase by') increaseBy(state: number, payload: number):

    number { /* ... */ } @Action('Decrease by') decreaseBy(state: number, payload: number): number { /* ... */ } @Action('Set') set(state: number, payload: number): number { /* ... */ } } Creating a duck family
  9. import { reducerFrom } from '@co-it/ngrx-ducks'; export class Counter {

    /* @Action declarations */ } export const counterReducer = reducerFrom(Counter); Automatic reducer generation
  10. A Duck allows you to focus on mutation logic and

    omits maintenance effort of reducer functions.
  11. Automatic service generation import { Ducksify } from '@co-it/ngrx-ducks'; @Ducksify<number>({

    initialState: 0 }) export class Counter { @Action('Increase by') increaseBy(state: number, payload: number): number { /* ... */ } . . . }
  12. @Ducksify behind the scenes Counter @Duckisfy • produces a facade

    • connects facade to Store • registers facade as service @Component • @Inject facade Duck<Counter> Duck<Counter> code transformation
  13. Usage of a Duck-Service export class CounterComponent implements OnInit {

    constructor(@Inject(Counter) private counter: Duck<Counter>) { } }
  14. Dispatch an action export class CounterComponent implements OnInit { constructor(@Inject(Counter)

    private counter: Duck<Counter>) { } ngOnInit(): void { this.counter.incrementBy(42); } } // this.store.dispatch(incrementBy({ payload: 42})) NgRx Classic or
  15. A Duck allows to dispatch an action using a simple

    function taking an optional payload. ( )
  16. Reuse existing selectors import { bindSelectorGroup } from '@co-it/ngrx-ducks'; @Ducksify<number>({

    initialState: 0 }) export class Counter { select = bindSelectorGroup(selectors); . . . }
  17. Consume selector as Observable export class CounterComponent implements OnInit {

    count$: Observable<number>; constructor(@Inject(Counter) private counter: Duck<Counter>) { this.count$ = this.counter.select.currentCount; } }
  18. Use initiating actions import { effect } from '@co-it/ngrx-ducks'; @Ducksify<number>({

    initialState: 0 }) export class Counter { set = effect<number>('Set'); . . . }
  19. Dispatch initiating actions export class CounterComponent implements OnInit { constructor(@Inject(Counter)

    private counter: Duck<Counter>) { } ngOnInit(): void { this.counter.set.dispatch(42); } }
  20. A Duck used in an effect @Injectable() export class CounterEffects

    { setCounter = createEffect(() => this.actions$.pipe( whereType(this.counter.set), delay(2000), map(action => this.counter.setSuccess.action(action.payload)) ) ); constructor( private actions$: Actions, @Inject(Counter) private counter: Duck<Counter> ) {} } Calling the action creator
  21. Summary • A Duck ... ◦ is a dynamic facade

    that can be injected in a Component ◦ composes read- and write-API and provide a dynamically typed facade. ◦ automatically generates action creators & reducer functions. • NgRx Ducks ships with Schematics ◦ Try @co-it/ngrx-ducks:duck <path>/<name>
  22. Special thanks to Sascha Nuissl Marcel Hoyer Wes Grimes ...introducing

    me to the Ducks-Pattern ...creating the logo for NgRx Ducks ...helping me with the slides @pixelstatic @saschanuissl @wesgrimes Thomas Skalnik ...creating the schematics for NgRx Ducks @skydever
  23. Thanks you for watching! @GregOnNet medium.com/@gregor.woiwode co-IT.eu GmbH - Inspire

    to change Gregor Woiwode Creator of NgRx Ducks https://github.com/co-it/ngrx-ducks
  24. Images by - Free-Photos from Pixabay - Alain Audet from

    Pixabay Icon s from Flaticon by - Freepik - Good Ware - Smashicons Credits