I don't completely understand where and how I need to declare observables / subjects in Angular component.
Currently I develop a website which interacts with MovieDB API and I have everything working, but at the same time I understand that my code is bad, because there aren`t cleanups of subscriptions after destroying the component, but to do these cleanups I need at least understand how to use RxJS correctly.
I think that my usage is incorrect, because I have new subscription on every interaction with the page. Also as I understand they need to be declared in constructor.
The idea of this page is that there is an input form where user types the query and checks the radio-button to choose what to search: 'tv' or 'movies'. When there are the results of searching, there appears a button to expand the results.
So, here is the code:
import {Component, OnDestroy} from '@angular/core';
import {ISearchParams} from '../../models/search-params.interface';
import {ShowService} from '../../services/show.service';
import {IResultsIds} from '../../models/results.interface';
import {distinctUntilChanged} from 'rxjs/operators';
import {Subscription} from 'rxjs';
@Component({
selector: 'app-search',
templateUrl: './search-tab.component.html',
styleUrls: ['./search-tab.component.scss']
})
export class SearchTabComponent implements OnDestroy {
searchParams!: ISearchParams;
searchResults!: IResultsIds;
searchSub!: Subscription;
showMoreSub!: Subscription;
constructor(private movieService: ShowService) {
}
search(searchParams: ISearchParams): void {
this.searchParams = searchParams;
this.searchSub = this.movieService.search(searchParams)
.pipe(distinctUntilChanged())
.subscribe(results => {
this.searchResults = results;
});
}
showMore(): void {
if (!this.isFinished()) {
this.searchParams.page++;
this.showMoreSub = this.movieService.search(this.searchParams)
.subscribe(results => {
this.searchResults!.ids.push(...results.ids);
});
}
}
isFinished = () => this.searchParams.page >= this.searchResults!.total_pages;
ngOnDestroy(): void {
// this.searchSub.unsubscribe();
// this.showMoreSub.unsubscribe();
}
}
And the HTML:
<main class="main-content search-container">
<app-search-form (searchParams)="search($event)"></app-search-form>
<div class="results" *ngIf="searchResults">
<app-show-description *ngFor="let id of searchResults.ids"
[showType]="searchParams.type"
[showId]="id"></app-show-description>
</div>
<button *ngIf="searchResults && !isFinished()"
(click)="showMore()"
class="load-btn more-btn">show more...</button>
</main>
I will be very grateful if you help me and tell where I made mistakes. On more time, everything works this way, but I want to understand usage of RxJS.
UPD @H3AR7B3A7 thank you very much, you have clearified my knowledge a bit! but now I have another misunderstanding: how to transform 2 array observables into one? I have googled but I can't find the solution to my problem: I have function to load more movies - it has to extend the array of distinctMovies$, which looks just like an array of numbers (ids), but I can't join two arrays, all I get is [...], [...] but not [......]
I tried this:
showMore(): void {
this.searchParams.page++;
this.distinctMovies$ = concat(this.distinctMovies$,
this.movieService.search(this.searchParams)
.pipe(pluck('ids')))
.pipe(tap(console.log));
}