0

I have an Angular 4 application, which uses angular-router to navigate between different pages (lets call them pageA and pageB). pageA and pageB load same list of items - sharedState.items (which is reloaded from time to time). Here is the redux store structure for those pages:

{
    pageA: { ... }
    pageB: { ..., noItemsMessage: null }
    sharedState: { items: [], popupMessage: null, ... }
}

Everything is good when items are loaded successfully from the server (sharedState gets updated and both pages show changes when they are navigated to). But the problem occurs when server returns an error - I want to show error message on pageA in the popup, using sharedState.popupMessage - which is a general way to show error in popup in the app. But on pageB it should be a small local tooltip, which is in pageB.noItemsMessage state property.

I have redux-observable epics registered to listen to 'LOAD_ITEM_FAIL' action for both pageA and pageB side-effects, but doing different things like:

pageALoadItemsFailEpic = actions$ => actions$.ofType('LOAD_ITEM_FAIL')
    .switchMap(x => { type: 'SHOW_POPUP', message: 'Error occured' })

pageBLoadItemsFailEpic = actions$ => actions$.ofType('LOAD_ITEM_FAIL')
        .switchMap(x => { type: 'UPDATE_PAGE_B_TOOLTIP', message: 'Error occured' })

And the problem is that when I am on the pageB - error tooltip is shown and popup with error message as well, because pageALoadItemsFailEpic is also executed. (And I don't want to show the popup on pageB.)

The simplest way seems to track which page is currently navigated to and perform side effects based on that. But I wonder if there is a better solution? Or is there maybe a better way to architecture this kind of functionality? Is there a way to turn on/off epics, based on whether page is currently active or not? Thanks in advance!

Ostap
  • 353
  • 1
  • 4
  • 8

1 Answers1

2

I don't use redux but ngrx but i am pretty sure principles are the same.

You should not show/hide UI elements outside your components. What you should do is have properties on your state like:

PageAErrors:any,
PageBErrors:any

and then your PageA component should subscribe to PageAErrors observable and Page B subscribe to PageBErrors observable. And then each component on its own decides what to do (popup, baloon, tooltip, whatever) when observable of its interest (with error) emits new value.

Always stick to basics: this is a messaging architecture, lososely coupled and there should be no direct, imperative link between components<>epics<>state. epics fire actions which in turn (through reducer) update state, components listen and react to state changes.

Otherwise you end up maintaining UI logic that belongs to component only (popup show, for example) all over the code.

dee zg
  • 13,793
  • 10
  • 42
  • 82