Search code examples
ngrx

Factory selector does not fire subscription with state update


Referencing this NGRX ticket, I am seeing an oddity where a code-based subscription to a factory selector does not fire with state updates, however, the async pipe does work.

To clarify, if I set up a public observable property on a component and bind the HTML to it with an async pipe, the value will update as the state updates.

component.ts

public test$: Observable<ChatInteraction>;
[...]
this.test$ = this.store
      .select(getNewMessageForChat(this.chat.chatId));

component.html

test: {{(test$ | async).message}}

Then I end up with output like

test: test1
test: test2
etc etc

However, if I try to subscribe to that same observable, it fires once when the subscription is created, but never again as the state updates.

component.ts

this.store
      .select(getNewMessageForChat(this.chat.chatId))
      .subscribe(() => {
        if (this._calculateScrollDistanceFromBottom(this.chatWindowElem.nativeElement) <= 20) {
          this._scrollToBottom();
        }
      });

If I put a breakpoint on that if statement, it does not get hit as I update state.

Any ideas why?


Solution

  • Figured it out. Turned out I had an undefined object reference in my subscription, which caused the subscription to break on its first run and resulted in it no longer firing. This was difficult to catch as it turns out the subscription code has a try/crush in it unless a setting is set.

    __tryOrUnsub(fn, value) {
            try {
                fn.call(this._context, value);
            }
            catch (err) {
                this.unsubscribe();
                if (config.useDeprecatedSynchronousErrorHandling) {
                    throw err;
                }
                else {
                    hostReportError(err);
                }
            }
        }
    

    hostReportError didn't bubble anything up so to me it looked like it just wasn't firing anymore.