Ngrx - createSelector vs Observable.combineLatest

I just ran into custom selectors @ngrx , and I'm just not surprised at this feature.

Following their use case booksfor selectedUser, I cannot give a real reason to use a custom selector, for example:

export const selectVisibleBooks = createSelector(selectUser, selectAllBooks, (selectedUser: User, allBooks: Books[]) => {
    return allBooks.filter((book: Book) => book.userId === selectedUser.id);
});

instead of something like:

export const selectVisibleBooks = Observable.combineLatest(selectUser, selectAllBooks, (selectedUser: User, allBooks: Books[]) => {
    return allBooks.filter((book: Book) => book.userId === selectedUser.id);
});

I tried to convince myself that memoization createSelector is an important part, but, as I understand it, he can not meet these improved performance to non-primitive values, so it generally will not save computation for non-primitive fragments, which with the help of Rx distinctUntilChangeda combineLatestcan be solved.

So what I missed, why should I use @ngrx/selector?

Thanks in advance for any ideas.

+4
1

, , , , . , docs, - memoization reset, , , , . , , combineLatest.

, , . , store.select(x => foo.bar.baz) , store.select(selectBaz). . , , . , - , , . . -, , .

createSelector , . , , . :

const selectParentVmById = (id: string) => createSelector<RootState, Parent, Child[], ParentVm>(
    selectParentById(id),
    selectChildren(),
    (parent: Parent, children: Child[]) => (<ParentVm>{
        ...parent,
        children: children.filter(child => parent.children.includes(child.id))
    })
);

selectParentVmById , selectChildren() , , - . , , , . , , , (, ). , createSelector combineLatest memoization.

, .

, , , . distinctElements(), distinctUntilChanged(), , .

:

import { Observable } from 'rxjs/Observable';
import { startWith, pairwise, filter, map } from 'rxjs/operators';

export const distinctElements = () => <T extends Array<V>, V>(source: Observable<T>) => {
    return source.pipe(
        startWith(<T>null),
        pairwise(),
        filter(([a, b]) => a == null || a.length !== b.length || a.some(x => !b.includes(x))),
        map(([a, b]) => b)
    )
};

:

const selectParentVmById = (store: Store<RootState>, id: string): ParentVm => {
    return store.select(selectParentById(id)).pipe(
        distinctUntilChanged(),
        switchMap((parent) => store.select(selectChildren()).pipe(
            map((children) => children.filter(child => parent.children.includes(child.id))),
            distinctElements(),
            map((children) => <ParentVm> { ...parent, children })
        ))
    );
}

, . shareReplay(1) .

+1

Source: https://habr.com/ru/post/1691979/


All Articles