🔥NgRx Selector Dependency Hell🔥

Zsolt Deak
Feb 26 · 3 min read

Selectors are pure functions used for obtaining slices of store state. @ngrx/store provides a few helper functions for optimizing this selection. Selectors provide many features when selecting slices of state:

Portability, Memoization, Composition, Testability, Type Safety

Photo by israel palacio on Unsplash

Being pure functions, selectors don’t need to be enclosed by a class, service, or namespace. As NgRx’s guideline suggests exporting them from a module. For actions a more convenient way to handle cohesion is namespacing, for selectors this might pose problems. Actions are also — or at least should be — pure functions, but it’s key difference that they don’t depend on each other. On the other hand selectors frequently do. Consider the following example:

With a bigger codebase, we might want to separate them by sub states, for this example these being selectedUser and allBooks , books and users. It’s fairly clear this code snippet won’t work: Angular will throw warnings about circular dependencies, but tests for instance will not even start. Why? Let see, if we wanted to use selecVisibleBooks then the test would want to process selectUser which would then lead back to selecAllBooks but at that point, processing of BookSelector hasn’t finished, hence we’d reference a selector on undefined .

What BookSelector?

Okay, but why would we use namespaces if the guide suggests modules? Having lots of sub states we might face an issue of the same generic selector names repeating, like getAll which can lead to confusion. This could be also avoided with tricks such as export * as NamedSelector from "..."; , which is exactly one line and one file more than using a namespace to begin with for the same effect. There is no namespace object to be defined this way though, so at least it’d solve the circularity problem, right? Wrong. Same 💩, different story:

Modules don’t work either

Why is it throwing an error? Is it truly a circular dependency? In fact, not at all. Only our namespaces/modules have circularity, but the selectors as pure functions would only have a circle, if starting from selectVisibleBooks the call stack would lead back to selectVisibleBooks itself. The problem resides solely in the semantics of the selectors: we need to define a clear dependency direction between the two namespaces. Looking at the example there are two cross-dependent selectors: selectVisibleBooks and selectAuthor . The former clearly returns books and uses users for the computation, so seems right where it is. On the other hand selectAuthor could go either way, uses both state slices and calculates a primitive from them. It would make sense to define the direction as BookSelector -> UserSelector and add selectAuthor to BookSelector .

At first sight this could seem blatantly obvious, but as projects grow setting simple rules such as direction of selector namespace dependencies saves future headaches and heavy refactors.

Last but not least the working solution in action, since a green test is always pleasure for the engineer’s eyes:

It’s working!! 🎉

Sign up for Top 10 Stories

By The Startup

Get smarter at building your thing. Subscribe to receive The Startup's top 10 most read stories — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +786K followers.

Zsolt Deak

Written by

Software Engineer at Betsson

The Startup

Get smarter at building your thing. Follow to join The Startup’s +8 million monthly readers & +786K followers.

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store