NgRx Ducks | How to use selectors

Gregor Woiwode
4 min readMay 6, 2019

--

In my previous Articles about NgRx Ducks, I have shown how a Duck-service can be used to easily dispatch actions or handle side-effects. These techniques belong to the write-API the needs to be implemented if you are using Redux. This article focuses on the read-API. You will learn how NgRx Ducks integrates NgRx selectors seamlessly to provide a simple API for consuming components.

🏃‍♂️ Let’s start.

Update 🥳

Now, NgRx Ducks has its own Docs-Page showcasing all features.
Happy Reading: https://co-it.gitbook.io/ngrx-ducks/

Show me the code

The code discussed in this article is available on ⚡️ StackBlitz. There you will have a deeper look at how the respective code-parts are related to each other.

Pick all the things

To allow reading state from the Store a Duck provides a method called pick that accepts NgRx-selectors. Behind the scenes pick just uses store.pipe(select(...)) to get the desired information.

Let’s assume you already have a selector in your NgRx project like the following.

const visitCounter = createFeatureSelector<CounterState>('counter');export const currentCount = createSelector(
visitCounter,
c => c.count
);

It just reads the current count from the store and automatically informs when the count changes.
Using pick you can use selectors like this easily.

...
import * as selectors from '../store/counter.selectors';
@Component({ ... })
export class CounterComponent {
count$: Observable<number>;
constructor(@Inject(CounterDuck) private counter: Duck<Counter>) {
this.count$ = this.counter.pick(selectors.currentCount);
}
}

The method pick enables you to interact with the store without the need to inject the Store-dependency. You can read data from each slice of the store. If you already use the Store as the one and only API for your component the Duck-Service simply replaces the Store.

Furthermore, the NgRx Ducks library allows you to make selectors part of your Duck-service.

Turn selectors to consumable Observables

Instead of using pick you also can add a selector to your Duck-service. The NgRx Ducks library implements a convention simplifying the usage of a selector a bit.

import * as selectors from './counter.selectors';@Ducksify<CounterState>({
initialState: {
count: 0,
isLoading: true
}
})
export class Counter {
current$ = selectors.currentCount;
// ...
}

The code above shows that selectors.currentCount is assigned to a property current$ . If you are familiar with the Finnish Notation for observables you already know what this means. The Duck-service will wrap the selector into a call like this: store.pipe(select(selectors.currentCount)).

For the consuming component, the selector automatically becomes a consumable Observable.

A selector gets transformed into an Observable.

How this works

You may ask how this can be done. How can a selector be turned into something else?

The decorator @Ducksify does the code transformation. It analyses if a property is a selector. If a selector is detected it is used within the select-operator coming from NgRx. This process is called Monkey-Patching.

Since we are in TypeScript-Land it is possible to add type-information to have the nice auto-complete-feature in your IDE. This is one reason why a Duck needs to be injected with the generic Type Duck<T>. Using this type the structure of the Service gets analysed and if a selector is detected Duck<T> tells the TypeScript-Compiler that the corresponding property becomes an Observable.

A Duck performs typed monkey patching 🍽 serving the component a simple API.

Benefits

The integration for selectors was added to the Ducks-library because it enables to compose the read- and write-API that is naturally separated using Redux.

A component just needs the Duck-service to discover all possible queries or mutations concerning a certain state slice. This solves one serious problem that bigger NgRx projects have. You do not need to look up multiple files to see what others already have implemented. The risk to reimplement an action or a selector will be reduced by using NgRx Ducks.

Recapitulation

  • pick can be used to read data from each state slice
  • selectors can be directly integrated into the Duck-service
  • selectors get transformed by @Ducksify to be consumed as Observables
  • The 🐥 Duck adds higher discoverability to already implemented features.
  • The 🐥 Duck composes read- and write-API and provide a dynamically typed facade.

That’s it ✨

Thanks for reading the third article about NgRx Ducks. I hope you enjoyed it. 🤗 If you have any further questions or ideas to improve this project please leave me a comment below.

You also can send me a message on Twitter: @GregOnNet
Since a new article has been published I will tweet about it as well.

Rock On And Code
Gregor

Related Articles

I have written several articles about NgRx Ducks. Basically, it is all about automating the creation of an easy-to-use facade. If you want to know more about Facades itself I recommend to read Thomas Burleson’s article NGRX + Facades.

--

--

Gregor Woiwode

Gregor loves to build tools 🛠 that enable developers to be more productive. He also enjoys 🏃‍♂️ or trying his hand at hobby cooking 👨‍🍳.