createDuck

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 ngrx.io | Actions) 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.

*/

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>());
}

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']
    });
  );
}

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

Last updated