Fixable |
---|
Prefer combining selectors at the selector level.
A selector is a pure function that is used to derive state. Because a selector is a pure function (and a synchronous function), it's easier to test.
That's why it's recommended to build a view model by composing multiple selectors into one selector, instead of consuming multiple selector observable streams to create a view model in the component.
Examples of incorrect code for this rule:
export class Component {
vm$ = combineLatest(
this.store.select(selectCustomers),
this.store.select(selectOrders),
).pipe(
map(([customers, orders]) => {
return customers.map((c) => {
return {
customerId: c.id,
name: c.name,
orders: orders.filter((o) => o.customerId === c.id),
}
})
}),
)
}
export class Component {
customer$ = this.store
.select(selectCustomers)
.pipe(withLatestFrom(this.store.select(selectActiveCustomerId)))
.pipe(
map(([customers, customerId]) => {
return customers[customerId]
}),
)
}
Examples of correct code for this rule:
export selectCustomersAndOrders = createSelector(
selectCustomers,
selectOrders,
(customers, orders) => {
return {
customerId: c.id,
name: c.name,
orders: orders.filter((o) => o.customerId === c.id),
}
}
)
export class Component {
vm$ = this.store.select(selectCustomersAndOrders);
}
export selectActiveCustomer = createSelector(
selectCustomers,
selectActiveCustomerId,
([customers, customerId]) => {
return customers[customerId];
}
)
export class Component {
customer$ = this.store.select(selectActiveCustomer);
}