I created a component that triggers an onScrollEnd
event once the last item in a virtual list is displayed. This event initiates a new API request to fetch the next page and combine it with the previous results using the scan
operator.
In addition, this component features a search field that triggers an onSearch
event.
Now, I am facing an issue of clearing the previously accumulated results from the scan
operator when a search event occurs. Do you have any suggestions on how to handle this situation effectively, or should I consider refactoring my current approach?
const loading$ = new BehaviorSubject(false);
const offset$ = new BehaviorSubject(0);
const search$ = new BehaviorSubject(null);
const options$: Observable<any[]> = merge(offset$, search$).pipe(
// 1. Start the loading indicator.
tap(() => loading$.next(true)),
// 2. Fetch new items based on the offset.
switchMap(([offset, searchterm]) => userService.getUsers(offset, searchterm)),
// 3. Stop the loading indicator.
tap(() => loading$.next(false)),
// 4. Complete the Observable when there is no 'next' link.
takeWhile((response) => response.links.next),
// 5. Map the response.
map(({ data }) =>
data.map((user) => ({
label: user.name,
value: user.id
}))
),
// 6. Accumulate the new options with the previous options.
scan((acc, curr) => {
// TODO: Don't merge when search$.next is triggered
return [...acc, ...curr]);
}
);
// Fetch next page
onScrollEnd: (offset: number) => offset$.next(offset);
// Fetch search results
onSearch: (term) => {
search$.next(term);
};