@ngxs-logger-plugin not showing nextState with some Observables

  angular, ngxs, rxjs

I am a bit unclear on the internal conditions for getting the @ngxs-logger-plugin working. I modeled this action on the NGXS example for an action getting data from an API, which calls the API, then sets the state via tap:

import {Category} from '../interfaces/Category';
import {Action, State, StateContext} from '@ngxs/store';
import {HttpClient, HttpParams} from '@angular/common/http';
import {Observable} from 'rxjs';
import {tap} from 'rxjs/operators';
import {GetCategories} from '../actions/category.action';
import {Injectable} from '@angular/core';
import * as _ from 'underscore';

export class CategoryStateModel {
  categories: Category[];
}

@State<CategoryStateModel>({
  name: 'categories',
  defaults: {
    categories: undefined
  }
})
@Injectable()
export class CategoryState {
  stateChanges = 0;

  constructor(private http: HttpClient) {
  }

  @Action(GetCategories)
  getCategories({getState, setState}: StateContext<CategoryStateModel>, action: GetCategories): Observable<any> {
    const params = new HttpParams()
      .set('person_id', action.person_id.toString())
      .set('year', action.year.toString());
    return this.http.get<any[]>('/api/categories', {params}).pipe(
      tap(result => {
        const state = getState();
        _.each(result, (category: Category) => {
          _.each(category.winners, winner => winner.declared = new Date(winner.declared));
        });
        setState({
          ...state,
          categories: result
        });
        this.stateChanges++;

        console.log('CATEGORIES State Change #' + this.stateChanges);
      })
    );
  }


}

This works fine, and I get nice logging in the console with the state before and after.

However, I want to wrap that API call to only call once I’m authenticated and connected to my socket server, so I add that using mergeMap():

import {Category} from '../interfaces/Category';
import {Action, State, StateContext} from '@ngxs/store';
import {HttpClient, HttpParams} from '@angular/common/http';
import {Observable} from 'rxjs';
import {mergeMap, tap} from 'rxjs/operators';
import {GetCategories} from '../actions/category.action';
import {Injectable} from '@angular/core';
import * as _ from 'underscore';
import {ConnectednessService} from '../services/connectedness.service';

export class CategoryStateModel {
  categories: Category[];
}

@State<CategoryStateModel>({
  name: 'categories',
  defaults: {
    categories: undefined
  }
})
@Injectable()
export class CategoryState {
  stateChanges = 0;

  constructor(private http: HttpClient,
              private connectedService: ConnectednessService) {
  }

  @Action(GetCategories)
  getCategories({getState, setState}: StateContext<CategoryStateModel>, action: GetCategories): Observable<any> {
    const params = new HttpParams()
      .set('person_id', action.person_id.toString())
      .set('year', action.year.toString());
    return this.connectedService.connectedToAll$.pipe(
      mergeMap(() => this.http.get<any[]>('/api/categories', {params})),
      tap((result: Category[]) => {
        const state = getState();
        _.each(result, (category: Category) => {
          _.each(category.winners, winner => winner.declared = new Date(winner.declared));
        });
        setState({
          ...state,
          categories: result
        });
        this.stateChanges++;

        console.log('CATEGORIES State Change #' + this.stateChanges);
      })
    );
  }


}

This seems to work functionally: the tap() code is running, the state is being updated in my pages that are listening, but now I’m not seeing the "next state" line in the logger. I’ve run into this previously when I executed this setState() code in a map() instead of a tap() for whatever reason, but this is still in a tap, and the function is still returning the same Observable that was being returned before, so I don’t know why the logger isn’t working.

I also have a minor concern that even though it looks like everything is working, this is not isolated to the logger, and something internal to NGXS isn’t getting updated correctly, even though right now it looks like the app is working fine.

Source: Angular Questions

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.