Skip to content
This repository has been archived by the owner on Jan 10, 2018. It is now read-only.

select fire even when no change to slice state #435

Closed
rernens opened this issue Jul 4, 2017 · 1 comment
Closed

select fire even when no change to slice state #435

rernens opened this issue Jul 4, 2017 · 1 comment

Comments

@rernens
Copy link

rernens commented Jul 4, 2017

reopening issue #201

I have an application state built out of for sub states as below

export interface AppState {
  i18n: fromMultilingual.IMultilingualState;
  router: RouterState;
  uiState: fromMyTalentsShared.IUiState;
  storeData: fromMyTalents.IStoreData;
  organizationState: fromMyTalents.IOrganizationState;
}

const reducers = {
  i18n: fromMultilingual.reducer,
  router: routerReducer,
  uiState: fromMyTalentsShared.uiStateReducer,
  storeData: fromMyTalents.storeDataReducer,
  organizationState: fromMyTalents.organizationStateReducer,

};

my organizationState sub state is defined as following

// angular

// libs
import { TreeNode } from 'angular2-tree-component';

// app



export interface IOrganizationState {
  uiState: string;
  talentsUiState: string;
  talentID: string;
  groupID: string;
  entityID: string;
  nodes: TreeNode[];
  talent: any;
  group: any;
  entity: any;
  errorCode: string;
}

export const INITIAL_ORGANIZATION_STATE: IOrganizationState = {
  uiState: undefined,
  talentsUiState: undefined,
  talentID: undefined,
  groupID: undefined,
  entityID: undefined,
  nodes: [],
  talent: undefined,
  group: undefined,
  entity: undefined,
  errorCode: undefined
};

// selects specific slice from organization state
export const getOrganizationNodes = (state: IOrganizationState)  => state.nodes;
I am handling access to state slices in the following way

export const getOrganizationState = (state: AppState) => state.organizationState;
export const getOrganizationNodes = createSelector(getOrganizationState, fromMyTalents.getOrganizationNodes );

my reducers for the organizationState are as following

// lib
import * as _ from 'lodash';

// app
import { INITIAL_ORGANIZATION_STATE, IOrganizationState } from '../states/organization.state';
import { OrganizationState } from '../actions/index';

export function organizationStateReducer (organizationState: IOrganizationState = INITIAL_ORGANIZATION_STATE, action: OrganizationState.Actions): IOrganizationState {

  const newOrganizationState = _.cloneDeep( organizationState );

  switch (action.type) {

    case OrganizationState.ActionTypes.SET_UI:
      newOrganizationState.uiState = _.cloneDeep(action.payload);
      return newOrganizationState;

    case OrganizationState.ActionTypes.ORGANIZATION_NODES_LOADED:
    case OrganizationState.ActionTypes.ORGANIZATION_NODES_UPDATED:
      newOrganizationState.nodes = _.cloneDeep(action.payload);
      return newOrganizationState;

    case OrganizationState.ActionTypes.SELECT_TALENT:
      newOrganizationState.talentID = _.cloneDeep(action.payload);
      return newOrganizationState;

    case OrganizationState.ActionTypes.SET_TALENTS_UI:
      newOrganizationState.talentsUiState = _.cloneDeep(action.payload);
      return newOrganizationState;

    case OrganizationState.ActionTypes.TALENT_PROFILE_LOADED:
      newOrganizationState.talent = _.cloneDeep(action.payload);
      return newOrganizationState;

    case OrganizationState.ActionTypes.SET_ERROR:
      newOrganizationState.errorCode = _.cloneDeep(action.payload);
      return newOrganizationState;

    default:
      return organizationState;
  }
}

whatever action is issued on the organizationState, the following subscription get always invoked

this.nodes$ = this.store.select( getOrganizationNodes )
      .do( () => this.log.debug('Talents Treeview Component - data updated') )
      .map( ( nodes: TreeNode[] ) => _.cloneDeep( nodes ));

change is detected on on organizationState.nodes despite not being changed even if the Redux Devtools diff does not show any change in this slice of the state.

changing the above to

    this.sub = this.store.select( getOrganizationNodes )
      .subscribe( ( nodes: TreeNode[] ) => {
        this.log.debug('Talents Treeview Component people - state change notified');
        if (_.isEqual(this.nodes, nodes) === false ) {
          this.log.debug('Talents Treeview Component - data changed');
          this.nodes = _.cloneDeep( nodes );
        }
      });

it is my understanding that dictinctUntilChanged that is used by select should prevent the organizationStateNodes value being considered as changed when something else changes in the organizationState.

What's wrong here : my understanding of how select works or is there a bug

Angular 4.2.5
@ngrx (store/core/effects/router-store) latest

@rernens rernens changed the title selector fire even when no change select fire even when no change to slice state Jul 12, 2017
@robwormald
Copy link
Contributor

Please check this against NgRx v4, and if it’s still an issue, please reopen on https://github.com/ngrx/platform - Thanks!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants