Abdul Ahmad
Abdul Ahmad

Reputation: 10021

Angular - how to get state from ngrx and then perform http

I have a method on a service where I need to get some data from the redux store and use it in an http request, but I keep getting errors or the http request is not executed, here' what I'm trying:

class SettingService {
 updateSettings({ settings }) {
  return this.store.select(s => s.settings).map((state: any) => {
    const { id } = state.data;

    return this.http.put('route/' + id, { settings }).pipe(map((response: any) => {
      const { data } = response;
      this.store.dispatch(new GetSettingsSuccess({ data }));
      return data;
    })).pipe(catchError(this.errorHandlerService.handleError));
  });
 }
}

Errors I'm getting are things like

Property 'map' does not exist on type 'Observable'

the way I'm using this is importing the service into a component, then:

this.settingService.updateSettings({ settings }).subscribe();

the method is called, but for some reason the http request doesn't happen. Am I supposed to subscribe to the http request too? or should I use pipe instead of map and give it multiple operators instead?

Upvotes: 2

Views: 1433

Answers (3)

frido
frido

Reputation: 14139

You should chain multiple operators in a pipe. Use switchMap (or even mergeMap) to map your store output to the Observable from the Http request and then do your other tasks each in its own operator. You get much cleaner code this way.

It should look something like this:

updateSettings({ settings }) {
  return this.store.select(s => s.settings)
    .pipe(
      // map the state from your store to the http request
      switchMap((state: any) => this.http.put('route/' + state.data.id, { settings })),
      // map the http response to the data your care about
      map((response: any) => response.data),
      // execute any other task with that data
      tap(data => this.store.dispatch(new GetSettingsSuccess({ data }))),
      // catch errors if they occurr
      catchError(this.errorHandlerService.handleError),   
    );

You then subscribe to the returned Observable and your http request will be executed after a value from the store is emitted.

this.settingService.updateSettings({ settings }).subscribe(
  // you'll have access to your data from the http response here
  data => doSomething(data) 
);

Upvotes: 3

Aragorn
Aragorn

Reputation: 5289

Here's a Pseudo code for what you might want to try:

 updateSettings({ settings }) {
   // use store select through a reducer:
    return this.store.select('your_reducer_here').subscribe( state => {
      //get id from your state  
      const id = state.data;

      //use that id in your http call
      return this.http.put('route/' + id, { settings }).pipe(map((response: any) => {
        const { data } = response;
        this.store.dispatch(new GetSettingsSuccess({ data }));
        return data;
      })).pipe(catchError(this.errorHandlerService.handleError));
    });
    })
}

Upvotes: 1

J. S.
J. S.

Reputation: 2374

You call map on a observable here this.store.select(s => s.settings).map((state: any) You need to use a pipe(map()). In this line you do it right: return this.http.put('route/' + id, { settings }).pipe(map((response: any)

Upvotes: 1

Related Questions