trigger
trigger

Reputation: 497

ngrx subscribe in service or pass data from component?

I need advice, i need data from store in service (my service use Angulartics to send data to Google Analytics). I stored all needed data as object in store, what is better:

  1. Subscribe to store in my service, which send data each time to analytics.
  2. Inject store to each component, get data - send to service, then unsubscribe?

Also, i dispatching action when getting information in service. How i can create store field listener ? (get the data when this field will not be undefined)

Upvotes: 2

Views: 5303

Answers (3)

Lapenkov Vladimir
Lapenkov Vladimir

Reputation: 3218

I read this article https://brianflove.com/2017/11/01/ngrx-anti-patterns/ and managed not to subscribe explicitly in component or service and not to use any effects. First step is making service method listening for filter change, passing data via pipe to http request, then dispatching event with this data and returning observable of results

getCarItems(): Observable<ICarItem[]> {
 return  this.store.select(state => state.filter).pipe(
           map (source=> 
            {
            let productId=source.product ? source.product.productId:'';
            let brand = source.brand||'';            
            return({productId ,brand})                
            }),
        switchMap(value => this.http.get(`${this._baseUrl}api/caritems`,{params:value})),
        tap((list:ICarItem[]) => {        
          this.store.dispatch(new LoadCarItemsAction(list));}          
       ),
       switchMap(()=>this.store.select(state=>state.carItems))        
       )
}

Second step is to pass results to observable in component:

ngOnInit() {   
   this.carItems$ = this.myService.getCarItems();
  }

Upvotes: 0

Ritesh Waghela
Ritesh Waghela

Reputation: 3727

The first approach make sense, it will keep the logic in one place. What you need to do is to subscribe the store changes in your service and then send this to analytics service:

You can inject the Store service into your services. Use store.select to select slice(s) of state:

and inside the constructor of the service you can subscribe to the changes in your object like this:

this.store.select('keyName').subscribe( (data)=> {
 // do whatever you want with this data
});

Upvotes: 1

Sam Tsai
Sam Tsai

Reputation: 494

To me this is a good time to use @ngrx/effects. If you're already using @effects, then this shouldn't be too difficult to leverage. If not, a general pattern you might have to adopt is to move your Service call that loads the data (ie side effects like asynchronous service calls) to an effects file. Then you can do something like this to track analytic events. It has the benefits mentioned above of having it tracked in one place.

@Effect({ dispatch: false })
trackEvents = this.actions.pipe(
  ofType(...),
  tap(({ type, payload }) => {
    // make call to Angulartics
    this.angulartics2.eventTrack.next({ 
      action: type, 
      properties: { ...payload },
    });
  })
)

The code snipped is copied from https://blog.angularindepth.com/start-using-ngrx-effects-for-this-e0b2bd9da165#8a65.

Upvotes: 3

Related Questions