I am using the ngrx component store to get search results from the backend. However, I am unable to get a single value of the state, but instead I get an anonymousSubject. This anonymousSubject has the needed data but it is nested very deep in the object.
When I iterate over the returned observable in the html, I can get the right values, but now I need just a specific value (state.result[0]) but I cant do this.
Could someone clarify how I can acces a single value from the anonymousSubject? Thanks in advance!
Component.store
export interface SearchResultState {
result: Array<any>;
}
const defaultState: SearchResultState = {
result: []
};
@Injectable()
export class SearchStore extends ComponentStore<SearchResultState> {
constructor(
private readonly _http: HttpClient,
private readonly _notificationHandler: NotificationHandlerService
) {
super(defaultState);
}
readonly loadSearchResult = this.effect((trigger$: Observable<{ query: string; apiLinks: Array<string> }>) =>
trigger$.pipe(
debounceTime(200),
switchMap((action) => {
if(!action.query.length) {
return of(SearchActions.searchSuccess({result: {}}));
}
const headers: any = {
'Content-Type': 'application/x-www-form-urlencoded',
Accept: 'application/json',
};
const httpOptions: { headers: HttpHeaders } = {headers: new HttpHeaders(headers)};
const apiCalls = [];
for (const apiLink of action.apiLinks) {
apiCalls.push(this._http.get(`${API_URL}${apiLink}${action.query}`, httpOptions).pipe(
map((resp: any) => resp),
));
}
return forkJoin(apiCalls).pipe(
map((result) => {
console.log(result); //prints the right result
return this.setSearchResult({result});
}),
catchError(async error => {
this._notificationHandler.showError();
return SearchActions.searchFailed({error});
})
);
})
)
);
readonly setSearchResult = this.updater((state, result: any) => ({...state, result}));
readonly searchResult$: Observable<Array<any>> = this.select(state => {
console.log( 'state', state); //prints nothing unless used in the html
return state.result;
});
Component.ts (partly)
public _searchResult$ = this.searchStore.searchResult$;
public search($event: string): void {
this.searchStore.loadSearchResult({query: $event, apiLinks: this.apiLinks});
console.log(this._searchResult$); //prints the anonymousObject
this.searchResults.emit(this._searchResult$);
}
The reason that I got an anonymousSubject instead of the actual value of the store was that I did not yet subscribe to it. In the HTML, this was done with the async pipe.
To make it work, I added the lines :
ngOnInit(): void {
this.searchSub = this.searchStore.searchResult$.subscribe(state => {
console.log(state.result); //prints the right values
});
}
ngOnDestroy(): void {
this.searchSub?.unsubscribe();
}