Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing state in an NGRX effect

How can I access a piece of my state inside an effect? My current effect implementation (shown below) is triggered when a SEARCH_REUQUEST action is dispatched. However, I would like to access a piece of state to fetch some search parameters before calling my search service to initiate the HTTP request.

@Effect()
SearchRequest$ = this.actions$
  .ofType(fromSearchActions.SearchActionTypes.SEARCH_REQUEST)
  .pipe(
    switchMap((action: fromSearchActions.SearchRequest) => {
      return this.searchService
        .search(action.payload, action.enrichmentId)
        .pipe(
          map(response => {
            console.group("SEARCH effects");
            console.log(response);
            console.groupEnd();
            return new fromSearchActions.SearchRequestSuccess(response);
          }),
          catchError(error =>
            of(new fromSearchActions.SearchRequestFail(error))
          )
        );
    })
  );

Apparently there is an RxJS operator that I can take advantage of here, but I can't seem to understand how I'd go about modifying my existing effect implementation to incorporate that.

@Effect()
SearchRequest$ = this.actions$
  .ofType(fromSearchActions.SearchActionTypes.SEARCH_REQUEST)
  .withLatestFrom(this.featureStore.select(fromFeature.getCurrentSearchPageOptions))
  .pipe(
      switchMap((// How should this change? //) => { //Error
        return this.searchService
          .search(action.payload, action.enrichmentId, pageOptions)
          .pipe(
            map(response => {
              console.group("SEARCH effects");
              console.log(response);
              console.groupEnd();
              return new fromSearchActions.SearchRequestSuccess(response);
            }),
            catchError(error =>
              of(new fromSearchActions.SearchRequestFail(error))
            )
          );
      })
    )

I feel like I am close to a solution but I can't seem to put it together at the switchMap stage.

like image 296
cyberbeast Avatar asked Oct 17 '18 05:10

cyberbeast


People also ask

Can I use selector in effect NgRx?

The idea is to inject a Storage instance into the Effect. Then, you can use it in your effect factory method. Now, you can use your storage object to get data from your current state. (You can use a Selector.)

Where is NgRx state stored?

Where Does NgRx Store Data? NgRx stores the application state in an RxJS observable inside an Angular service called Store. At the same time, this service implements the Observable interface. So, when you subscribe to the store, the service actually forwards the subscription to the underlying observable.

How do you call an effect in NgRx?

You need to run this command npm install @ngrx/effects — save to install required dependencies. You have to define the actual services to make the API calls. Finally, you need to register all the effects with the EffectsModules and import this module into your main module or feature module.

When should you not use NgRx?

When should you not use NgRx? Never use NgRx if your application is a small one with just a couple of domains or if you want to deliver something quickly. It comes with a lot of boilerplate code, so in some scenarios it will make your coding more difficult.


2 Answers

withLatestFrom: Combines the source Observable with other Observables to create an Observable whose values are calculated from the latest values of each.

You will get an array with the two data, you can find a guide in https://medium.com/@viestursv/how-to-get-store-state-in-ngrx-effect-fab9e9c8f087

your code could be like this:

@Effect()
    SearchRequest$ = this.actions.pipe(
        ofType(fromSearchActions.SearchActionTypes.SEARCH_REQUEST),
        withLatestFrom(this.featureStore.select(fromFeature.getCurrentSearchPageOptions)),
        switchMap(([action: Action, pageOptions: YourStateOptions]) => { // <-- pageOptions here
                return this.searchService
                    .search(action.payload, action.enrichmentId, pageOptions)
                    .pipe(
                        map(response => {
                            console.group("SEARCH effects");
                            console.log(response);
                            console.groupEnd();
                            return new fromSearchActions.SearchRequestSuccess(response);
                        }),
                        catchError(error =>
                            of(new fromSearchActions.SearchRequestFail(error))
                        )
                    );
            }
        )
    );
like image 185
Yoel Duran Avatar answered Oct 08 '22 05:10

Yoel Duran


withLatestFrom is definitely what you want. All you have to do is add the response to the parameters you pass in the switchMap. Like this (where pageOptions is the type for the slice of state you get from your selector):

switchMap(([action, options]: [fromSearchActions.SearchRequest, pageOptions]) => {

then you can use action as you did before and options would be what you get back from this.featureStore.select(fromFeature.getCurrentSearchPageOptions)

like image 2
Mitch McCutchen Avatar answered Oct 08 '22 04:10

Mitch McCutchen