Reputation: 6844
Let's say I have a store who holds ids and entities, and I need to combine them when they changed.
const state = {
ids: [],
entities: {}
}
const store = new BehaviorSubject(state);
Observable.combineLatest(
store.map(state => state.ids).distinctUntilChanged(),
store.map(state => state.entities).distinctUntilChanged(),
(ids, entities) => {
return ids.map(id => entities[id])
}
).subscribe(console.log);
store.next({ids: [1], entities: {1: {id: 1}}})
The problem with the above code is that the selector function will called twice because both the entities and the ids changed.
Is there any operator to solve this problem? If not, how can I create one that solves this?
I thought of a special test. To wait a certain time and unite their next() to one.
Note: It should support add, update, and delete.
The zip operator will solve, add and delete, because in this cases I'm updating both the ids and the entities, but update entity will not work.
Upvotes: 2
Views: 1729
Reputation: 11194
The withLatestFrom operator should do the job.
store.map(state => state.entities).distinctUntilChanged().withLatestFrom(
store.map(state => state.ids).distinctUntilChanged(), (entities, ids) => ids.map(id => entities[id])
).subscribe(console.log);
// Add
store.next({
ids: [1],
entities: {
1: {
id: 1,
name: 'A'
}
}
});
// Update
store.next({
...store.getValue(),
entities: {
1: {
name: 'B'
}
}
});
// Delete
store.next({
ids: store.getValue().ids.filter(id => id !== 1),
entities: {}
});
Upvotes: 1