0

I have a view that depends on 3 variables and it should be updated every time the state changes. I got the value Observables by selectors and used them by async pipe in my template.

The problem is that sometimes the state is changed but the view is not updated. This happens about every 20 times I refresh the page.

How do I know the state is updated? I subscribed on the store$ and logged the value on any change. So there is sometimes that I see the state changes on console but not in the view!

Is there a way to make sure the view is rendered correctly after all?

Code

In my component:

    this.homeFacade.loadOrderTypes();
    this.orderTypes$ = this.homeFacade.getOrderTypes();
    this.showRegisterButton$ = this.homeFacade.getRegisterButtonVisibility();

The loadOrderTypes function dispatches an action to load data from web service.

Update:

I extended the async pipe and tried some logging in that pipe. This is the log when the view is not updated:

@ngrx/store/update-reducers
12:45:31.729 async-test.pipe.ts:10 Subscribed async test pipe!
12:45:31.742 async-test.pipe.ts:10 Subscribed async test pipe!
12:45:32.236 client:52 [WDS] Live Reloading enabled.
12:45:32.273 home.reducer.ts:39 [Home Page] Load order type start
12:45:32.275 home.reducer.ts:39 [Home Page] Load order type success
12:45:32.277 home.reducer.ts:39 [Home Page] Check order type success

And this is the log when view is updated:

@ngrx/store/update-reducers
12:55:15.618 async-test.pipe.ts:10 Subscribed async test pipe!
12:55:15.631 async-test.pipe.ts:10 Subscribed async test pipe!
12:55:16.123 home.reducer.ts:39 [Home Page] Load order type start
12:55:16.126 home.reducer.ts:39 [Home Page] Load order type success
12:55:16.128 home.reducer.ts:39 [Home Page] Check order type success
12:55:16.137 async-test.pipe.ts:10 Subscribed async test pipe!
12:55:16.151 async-test.pipe.ts:10 Subscribed async test pipe!
12:55:16.151 async-test.pipe.ts:10 Subscribed async test pipe!
Moein Hosseini
  • 1,514
  • 3
  • 15
  • 33
  • can you provide more information? how tare the facade getters implemented? where is that code being called? a life-cycle hook? a minimal reproduction would be useful. – Jota.Toledo Nov 09 '19 at 09:34
  • This code is called in `ngOnInit` life-cycle hook. – Moein Hosseini Nov 09 '19 at 09:36
  • Move the initialization of both `orderTypes$` and `showRegisterButton$` into your constructor, or before invoking `loadOrderTypes` in the ngOnInit implementation. Might have an effect. Can you add the code from the facade getters? – Jota.Toledo Nov 09 '19 at 09:38
  • After wrapping the code with a `setTimeout` with 100ms, the problem solves! But it's not a nice way to fix it. – Moein Hosseini Nov 09 '19 at 10:02
  • This will not work always work. It might be that 100ms will not be enough in live situations. – Athanasios Kataras Nov 09 '19 at 15:09

1 Answers1

0

I would need to see the code, but my guess is that the view is rendered before the async pipe subscribes to the observable.

If you do and xhr request for the observable, then it might be that the view is rendered after the first response is received.

To make sure that is the case, decorate the async pipe. Check link here. In the constructor, do some logging and see which happens first. The state change, or the construction of the pipe.

Athanasios Kataras
  • 25,191
  • 4
  • 32
  • 61
  • Thanks for the guide! I extended the async pipe and tried some logging. I see the deference now! I updated the question please take a look at it. – Moein Hosseini Nov 09 '19 at 09:26
  • Try to wrap an *ngIf around the section of async components and when you get the first value from the observable, then show them (they will be initialized then). – Athanasios Kataras Nov 09 '19 at 15:10