Karty
Karty

Reputation: 1399

what is ngrx createSelector and createFeatureSelector?

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

Upvotes: 35

Views: 36176

Answers (3)

Chui Tey
Chui Tey

Reputation: 5564

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.

Upvotes: 5

Swatantra Singh
Swatantra Singh

Reputation: 1

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

Upvotes: 0

tlt
tlt

Reputation: 15221

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

Upvotes: 24

Related Questions