Reputation: 1399
I have been reading the code of ngrx example app and find two function calls
createFeatureSelector<AuthState>('auth');
and
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
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
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
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