what is ngrx createSelector and createFeatureSelector?
Asked Answered
W

3

33

I have been reading the code of ngrx example app and find two function calls

  1. createFeatureSelector<AuthState>('auth');

and

  1. createSelector(selectAuthState,(state: AuthState) => state.status);

What does this do?

export const selectAuthState = createFeatureSelector<AuthState>('auth');

export const selectAuthStatusState = createSelector(
  selectAuthState,
  (state: AuthState) => state.status
);
Whitesmith answered 29/10, 2017 at 10:21 Comment(0)
M
24

Its used as an optimization step for store slices selection. For example, if you return some heavy computation result for some store slice, then using createSelector will do memoization which means it will keep track of last input params to selector and if they are the same as current ones, it will return last result immediately instead of repeating computation.

ref: https://ngrx.io/guide/store/selectors

Mallet answered 29/10, 2017 at 10:27 Comment(7)
i am not sure what examples other than on provided link you would wantMallet
Indeed, the ref you provided does explain it quite succinctly.Dittany
ain't the point that auth can be lazyli loaded? For simply accessing a slice of state without computation i don't see a point in memoization, as only pointers should get passed what should be faster and more memory efficient than cashing the states sliceAutocade
@Lex you're right about that. For simple cases where you just return slice of the state you could very well use string selectors. But then you have another issue: code consistency & maintenance. In my opinion its a good practice to choose one approach and stick to it. For me, using createSelectors everywhere works good because then i have consistent pattern and if i ever choose to add some computation on top of pure string selection, there is only one place where i need to touch my code. But i guess that's a personal preference.Mallet
For anyone coming from first search result, I recommend reading this for detailed explanation ultimatecourses.com/blog/…Outing
It appears the reference link is now broken. Is there a possibility to fix it?Bebebebeerine
The correct link is (at least in January 2021): ngrx.io/guide/store/selectorsAgna
T
3

A little bit of background is in order

In Ngrx there is only one store. This is a giant global variable that any reducer can affect. In large programs, it'll be hard to reason over. We don't wish this on future maintainers.

How do we make it easier to reason over?

It is easier to comprehend if the store is partitioned into different features so that actions, reducers, and state that only pertain to a single feature set, for instance logging in, shopping cart, et c. are maintained in different areas/features.

Store
+-------------------------------+  {
|  Auth                         |    "auth": { username: "bob", country: "us" },
|  Cart                         |    "cart": { items: [] }
|  ...                          |  }
+-------------------------------+

As you probably already know, createSelector is used to select something from the store.

export const selectUserName = createSelector(
  (store: any) => store.auth as Auth, // in real life don't use any, see discussion later
  (auth: Auth) => auth.username)

We can simplify this into

const selectAuth = createSelector((store: any) => store.auth)
export const selectUserName = createSelector(selectAuth, auth => auth.username)

Further simplifying into

const selectAuth = createFeatureSelector<Auth>('auth')
export const selectUserName = createSelector(selectAuth, auth => auth.username)

There is an alternate way to writing this if you love rxjs

import { pipe } from 'rxjs'
const selectAuth = createFeatureSelector<Auth>('auth')
export const selectUserName = pipe(selectAuth, auth => auth.username)

Optional - discussion on 'any'

In highly complex applications, whenever you add another feature, the root (global) store's type changes. This can get unwieldy over time.

// define in state.js
type RootState = {
  auth: Auth
  cart: Cart
  // keep adding feature
  // ad infinitum...
}

// define in a auth.selector.js
const selectAuth = createSelector((store: RootState) => store.auth)

In this sense, using createFeatureSelector is preferred because you don't need to define RootState at all.

Twice answered 27/8, 2023 at 22:58 Comment(0)
F
0

So this is the selector functions(Pure Function).

  • createFeatureSelector('auth'): Defining the type of
    state in your case AuthState is interface which consists various
    things according to requirment. (The createFeatureSelector is a
    convenience method for returning a top level feature state. It
    returns a typed selector function for a feature slice of state)

  • createSelector(selectAuthState,(state: AuthState) => state.status):
    this line is use to select data based upon particular state in this case state of type AuthSate and assigning state.status to state along with selectAuthState

For better understanding u can refer to ngrx documentation NgRx

Fourhanded answered 17/4, 2023 at 5:7 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.