1

In an Angular 4 app using Redux (with ngrx-store), I have the following:

a smart component that calls a service

this.contentService.update(this.content).subscribe( data => {
  //output some success message
});

a service that calls an API and then dispatch an action

update(content: Content) {
  return this.http.put(`http://someendpoint/contents.json`, { content })
  .map( (updated_content: Content) => {
    this.store.dispatch( { type: 'SOME_KEY', payload: updated_content }  );
    return updated_content;
  });
}

this approach is working really well, no problem. But I don't know if this is the right way: would it be better to let the component handle the response of the API an dispatch the action to the store? Should I separate this? What are the pros and cons? I can't find a good article about this.

Christian Benseler
  • 7,907
  • 8
  • 40
  • 71

1 Answers1

2

Personally I'd like to separate any logic from a data-/rest-service.

Basically you have many, many ways of handling this - in a big application I'd not even call the service directly from within the component, but only through an @Effect via a dispatched action.

But there is no "one true" way, it all depends on the architecture/style that you define - just make sure you keep it consistent and don't introduce a new way with every component/service.

olsn
  • 16,644
  • 6
  • 59
  • 65
  • Thanks for the comment! I think I will follow this approach to separate the logic from my service, maybe using Effects (the app started very 'small' so I didn't think I will have much benefits using it, but now it's growing and maybe it's time to use them). :-) – Christian Benseler Jul 14 '17 at 14:37
  • 1
    I agree, Effects are the place to call services. – Matt Sugden Jul 14 '17 at 14:37
  • As I said: there is _no generic true solution_ - Refactoring always involves risk and most often requires quite a bit of effort - if you are the only developer working on the application and if it's below 50 files I'd personally don't invest the time and keep it as it is - with `@Effects` you might find other things that may annoy you, it will __not__ be magically better ;-) (though it might be cleaner, it will for sure be more work) – olsn Jul 14 '17 at 14:43
  • @olsn using Effects, when I dispatch some action, I can call my service. Then, inside it's subscribce() method, can I dispatch another action that my reducers will manage (and then change the state from my store)? Is this a good approach? – Christian Benseler Jul 14 '17 at 14:48
  • 1
    Close, but not entirely, have a look at this answer: https://stackoverflow.com/questions/44113814/when-to-use-ngrx-effect-in-angular2/44114123#44114123 (you can replace the "Failure" in the example with "Success" - the data-flow is the same) – olsn Jul 14 '17 at 14:53
  • @olsn thanks! Great link, I have understood this. BTW, do you have any tip about how to know when an Effect occurs? Let's explain: I can have an effect that calls my API to change some data. My component (frontend) shows a spinner when I dispatch the action to the Effect. But I don't know how to deal with this, to hide the spinner. Should I store some flag in my store? – Christian Benseler Jul 14 '17 at 15:17
  • Yes, the UI is bascially the representation of the store - so, if you want a spinner to show, the preferred solution is to set a flag in the store - I usually use a counter: it goes +1 for every started request and -1 for every ended(cancel, failed, succeeded) request, if the counter is > 0 => show a global spinner - that way you don't need a separate flag for each request - but if you still want a separate flag, that should be no problem as well – olsn Jul 14 '17 at 15:34
  • Alternatively you can also listen for actions in your component and have the service dispatch an action like "showContentSpinner" and "hideContentSpinner" -> that way you don't need to keep a state for the spinner (again... there is no right or wrong - just make sure that the solution fits your project and preferences) – olsn Jul 14 '17 at 15:36