Using NGRX and Angular 13 (just for clarity), I have a store with the following state:
export const initialState: SomethingState = {
data: null,
succeeded: false,
message: "",
errors: null,
};
And it has a feature selector as such:
export const selectSometingFeatureSelector = createFeatureSelector<SomethingState>("somthing");
Each time an API call completes the 'succeeded' value on the state is updated to true (provided no errors happened).
Then in each component where I use the 'selectSometingFeatureSelector' I always check to make sure the call has succeeded (and sometimes use a take(1) afterwards to auto unsubscribe). For example:
this.store.select(selectSometingFeatureSelector)
.pipe(
filter((state) => state.succeeded),
take(1),
map((state) => {
return state.data.items;
})
);
This is all fine (I think) but I find myself repeating the code a lot as all our states have 'succeeded' on them.
I wanted to move this to a selector so at first I wrote the below but it didn't work as the observable still fired before succeeded:
export const selectSomething = () =>
createSelector(
selectSomethingFeatureSelector,
(state: SometingState) => {
if(state.suceeded) {
return return state.data.items;
}
}
);
Looking at the code I'm not that surprised it didn't work (but it was worth a shot). Then after more research it seemed like this was the proper approach:
export const selectSomething = () =>
createSelector(
selectSomethingFeatureSelector,
filter((state: SomthingState) => state.suceeded === true)
(state: SometingState) => {
return return state.data.items;
}
);
Whilst the above seems to make perfect sense to me and I get no complaints in VS code I get the following error in the console:
TypeError: source.lift is not a function at filterOperatorFunction
So my question is in 2 parts:
The rxjs filter
operator is not meant to be used in `createSelector() but you can do a pipeable operator :
export const selectSomething = pipe(
select(selectSomethingFeatureSelector),
filter(val => state.suceeded === true)
map((state: SometingState) => state.data.items)
);
Which can be called like this :
store.pipe(selectSomething).subscribe(/* .. */);