11

I recently added ngrx store to my existing angular2 app in order to simplify the code and maintain a shared state. However I am confused about one part, I update my state from the server once in the beginning and after wards I just work on the state without checking the server. So what happens when for example some thing changes on the backend? Am i to check it every time when, I go the that page or is there a better way? Basically, I want to know what is the best practice for making sure that your state data is updated to show the server data?

Hasan Wajahat
  • 1,717
  • 2
  • 16
  • 16
  • Are you talking about server notification like [Server Sent Events](https://en.wikipedia.org/wiki/Server-sent_events) – Paul Samsotha Mar 16 '17 at 12:09
  • @Hasan Wajahat I got the same question, did you get any answer to it?? Thx – Hictus Oct 29 '18 at 14:38
  • @Hictus actually it is beyond the store's concern whether the backend has updated or not. I was using the store as a way to permanently store data on the frontend which it shoudn't be used for data that is prone to change. Basically the store is responsible for providing one place for all your data concerns . So you can either load data on page load and update in store if it has changed, or use something like web-sockets to initiate data load again. – Hasan Wajahat Oct 30 '18 at 16:57

1 Answers1

6

It is recommended to use NGRX Effects. When you implement NGRX Effects along with the Store, any HTTP side effects are handled by the Effects, which in turn, will use an Action in the Store to update the data. An Effect listens for the Action and uses the payload of the Action to perform a side-effect(HTTP). When the Effect finishes, it calls a new Action(either an Action for success or an action for failure) with a new payload, thus updating the data in the Store.

In the example in the Effects docs it shows an Effect for Login:

@Injectable()
export class AuthEffects {
  constructor(
    private http: Http,
    private actions$: Actions
  ) { }

  @Effect() login$ = this.actions$
      // Listen for the 'LOGIN' action
      .ofType('LOGIN')
      // Map the payload into JSON to use as the request body
      .map(action => JSON.stringify(action.payload))
      .switchMap(payload => this.http.post('/auth', payload)
        // If successful, dispatch success action with result
        .map(res => ({ type: 'LOGIN_SUCCESS', payload: res.json() }))
        // If request fails, dispatch failed action
        .catch(() => Observable.of({ type: 'LOGIN_FAILED' }))
      );
}

In this example, the Effect for Login listens for the LOGIN action. When the LOGIN action occurs, it uses the action's payload and performs an HTTP POST. When the HTTP POST returns, it either calls the action LOGIN_SUCCESS with the json response for the payload, or it returns the LOGIN_FAILED action.

This way, your Store is always kept in the loop on any side effects, such as HTTP. If one component updates a record in the database, the Effect should notify the Store so that all components subscribed to that data get the updated data.

Hope that helps.

Tyler Jennings
  • 8,761
  • 2
  • 44
  • 39
  • Thanks for the detailed answer Tyler. I partly understand what you mean. I had not opened NGRX Effects yet. But I will do that now, which will probably solve my concerns. Thanks a lot – Hasan Wajahat Mar 16 '17 at 12:24
  • There are a lot of examples out there that make Effects more complicated than it needs to be. Essentially your existing HTTP calls can be modified to act as Effects by listening for certain Actions and then returning new Actions with new payloads. The Action that the Effect listens for (such as `LOGIN` in the example above) may only need to immediately return an unmodified payload down to components, until the Effect calls a new Action with a new payload. – Tyler Jennings Mar 16 '17 at 12:36
  • 7
    Nice explanation for effects, but might not answer the question? My understanding of the Q: something on the server changes (e.g. User B finishes a Todo that's in my list). How does the server signal it back (Serverside events, web sockets, Mq...) and what piece of code would then trigger the action for the store? – stwissel Mar 17 '17 at 10:40
  • 1
    The question was posed mainly from the Angular/NGRX perspective. If you are using websockets, etc, it depends upon your backend architecture on how to set that up, and on the front end I would subscribe to the socket, but still use Effects to handle updating the Store from the websocket, thus updating all components subscribed to the store. NGRX Effects are designed to handle side-effects of any kind to abstract that away from the Store. Websockets, just like HTTP, is a side-effect. – Tyler Jennings Mar 17 '17 at 13:49
  • 1
    A side question would be, __"what if the user was already logged in?"__. How would you NOT call the api and instead either get the value/payload from the store or just do nothing? This would seem to apply to any resource you load from the api and save into the store. – trevorc Apr 07 '17 at 17:39
  • 1
    For me this does not answer the question - unless server is pushing updates to client . – Rui Marques Dec 22 '17 at 10:53
  • @RuiMarques : Perhaps the subject of this question will clarify the concept: https://stackoverflow.com/q/43154461/3396 – Robert Dean Dec 22 '17 at 14:28