NgRx Ducks
  • Introduction
  • @ngrx-ducks/core
    • Installation
    • Architecture
      • @StoreChunk
      • createDuck
      • getReducer
      • createMutableDuck
      • getMutableReducer
      • useSelect
      • useSelectors
      • useActions
    • Guides
      • Quick Start
  • Migrations
    • v15
  • Resources
  • FAQ
  • GitHub
  • Changelog
  • Sponsor
Powered by GitBook
On this page
  • Prerequisites
  • Action Dispatcher
  • Case reducer

Was this helpful?

  1. @ngrx-ducks/core
  2. Architecture

createDuck

Previous@StoreChunkNextgetReducer

Last updated 3 years ago

Was this helpful?

Prerequisites

In Redux Actions are used to set up the communication between components.

If you are not familiar with NgRx's Actions, we highly recommend to check their documentation (see ) first, before starting with Ducks.

Action Dispatcher

Using createDuck allows you to create a fully typed action that also contains the action dispatcher. A Duck can dispatch itself. It expects at least one parameter, the action type. The sample below demonstrates how the property greet becomes a duck, which means that greet now is a method that additionally contains a function dispatch.

import { createDuck, StoreChunk } from '@ngrx-ducks/core';

@StoreChunk()
export class Chunk {
  greet = createDuck('Hello 🐥');
}

/*
  
   greet()          // returns the action object: { type: 'Hello 🐥' }
   greet.dispatch() // dispatches the action to the store.

*/
import { Component, OnInit } from '@angular/core';
import { Chunk } from './chunk';

@Component({ /* ... */})
export class SomeComponent implements OnInit {
  constructor(private chunk: Chunk) {}
  
  ngOnInit() {
    this.chunk.greet.dispatch()
  }
}

Please note that createDuck.dispatch only works inside a class being annoted with @StoreFacade. You will receive an error in the console if you accidently forget@StoreFacade .

Often an action transports a payload. To define an action dispatcher with a payload, createDuck accepts a second parameter being able to set up a strictly typed action creator.

import { createDuck, dispatch } from '@ngrx-ducks/core';

@StoreChunk()
export class Chunk {
  greet = createDuck('Hello 🐥', dispatch<string>());
}
import { Component, OnInit } from '@angular/core';
import { Chunk } from './chunk';

@Component({ /* ... */})
export class SomeComponent implements OnInit {
  constructor(private chunk: Chunk) {}
  
  ngOnInit() {
    this.chunk.greet.dispatch('Good afternoon!')
  }
}

The second parameter needs to be filled with dispatch<TPayload> where TPaylod defines the type of the payload. In the component the dispatch-method now expects a parameter with the defined payload-type.

Case reducer

A duck can also contain a case-reducer.

A case-reducer is a method being executed when the corresponding action has been dispatched to the Store.

According to the shape of the case-reducer the action dispatcher is generated accordingly.

  1. If a case-reducer proceeds a payload the dispatcher expects a payload.

  2. If a case-reducer has no payload, the dispatcher expects no payload.

import { createDuck, dispatch } from '@ngrx-ducks/core';
import { State } from './state.ts';

@StoreChunk()
export class Chunk {
  greet = createDuck(
    'Hello 🐥',
    (state: SomeState, payload: string) => ({
      ...state,
      greetings: [...state.greetings, payload]
    });
  );
  
  noPayload = createDuck(
    'Hello 🤷‍♀️',
    (state: SomeState) => ({
      ...state,
      greetings: [...state.greetings, 'static mutation']
    });
  );
}
import { Component, OnInit } from '@angular/core';
import { Chunk } from './chunk';

@Component({ /* ... */})
export class SomeComponent implements OnInit {
  constructor(private chunk: Chunk) {}
  
  ngOnInit() {
    // case-reducer with payload
    this.someFacade.greet.dispatch('Good afternoon!');
    
    // case-reducer without payload
    this.someFacade.noPayload.dispatch();
  }
}
export interface State {
  greetings: string[];
}

One last question remains. How does the Store know about the case-reducers that has been added to a facade? Please read the section to learn how the reducer-function is generated by @ngrx-ducks and how the reducer gets finally bound to the Store.

ngrx.io | Actions
getReducer