* ngxs: 3.1.4
* @angular/core: 6.0.0
Stackblitz / Github link: https://stackblitz.com/edit/ngxs-simple-selector-issue
Select is triggering changes to the Selector created with map even though it does not change the value it uses.

The correct behavior would be that it does not fire the changes unless it is changed in the state the value that it is using
Hi @abalad
This is how memoization works. The returned value is cached based on the same input value.
In this case modifying the counter property results in a change to the container state which is then a new value passed to the issueWithMap selector which in turn results in a new calculated result.
You can get the behavior you are expecting by breaking down the issueWithMap selector's dependency to only be the other prop. This can be done using a composite selector but unfortunately (in ngxs v3) any composite selectors defined within the state class automatically take a dependency on the container class. So, to get this working you would need to move this selector to an unrelated class (this will be fixed in v4 and not necessary) so that it only takes a dependency on the provided selector.
Here is an example evolved from yours in a stackblitz:
https://stackblitz.com/edit/ngxs-simple-selector-issue-yrfhnp
@markwhitfeld Thank you. What I was left in doubt is because the:
@Selector () static others (state: CounterStateModel) {
聽聽聽聽 return state.other;
}
Does not issue changes even though I change the state.counter.
Already when I realize a map() or any transformation in him it is shot.
@Selector() static issueWithMap(others: CounterStateModel) {
return Object.keys(others)
}
That's what I do not understand.
The others selector re-evaluates when the state changes but because it returns the same value as before the subscription does not fire. The observable has a distinctUntilChanged operator on it so the same returned value is ignored.
The Object.keys(...) call is returning a new value whenever the selector is re-evaluated which gets through the distinctUntilChanged. This is why it is different to the others selector.
Hope this answers all your questions ;-)
@markwhitfeld Thank you so much. Now I understand.
To finalize the solution then final.
I've split my selectors into 2 files. One with the basic properties and the other file with all the selectors that the application will use.
usuario.state.ts
@State<UsuarioStateModel>({
name: 'usuario',
defaults: EntityStateModel.InitialState()
})
export class UsuarioState implements NgxsOnInit {
@Selector()
static selected(state: UsuarioStateModel) {
return state.selected;
}
@Selector()
static entities(state: UsuarioStateModel) {
return state.entities;
}
constructor( private usuarioService: UsuarioService) {}
@Action(LoadUsuarios)
loadUsuario( ctx: StateContext<UsuarioStateModel> ) {
return this.usuarioService.getAll().pipe(
map( ( usuario: Usuario[] ) => ctx.dispatch( new LoadUsuariosSuccess( usuario['data']) ) ),
catchError( ( error ) => ctx.dispatch( new OnError( error ) ) )
);
}
@Action(LoadUsuariosSuccess)
loadUsuarioSuccess( ctx: StateContext<UsuarioStateModel>, { payload }: LoadUsuariosSuccess ) {
EntityAdapter.addAll( payload, ctx );
}
.
.
.
usuario.selectors.ts
export class UsuarioSelectors {
@Selector([UsuarioState.entities])
static entities(entities: UsuarioStateModel['entities']) {
return new EntitySelector().getEntities( entities );
}
@Selector([UsuarioState.selected])
static selected(selected: UsuarioStateModel['selected']) {
return selected;
}
}
usuario.sandbox.ts
@Injectable()
export class UsuarioSandbox {
@Select( UsuarioSelectors.selected ) usuarioSelected$: Observable<Usuario>;
@Select( UsuarioSelectors.entities ) usuariosCollection$: Observable<Usuario[]>;
constructor( private store: Store ) {}
loadUsusuarios() {
this.store.dispatch( new LoadUsuarios() );
}
addUsuario( usuario: Usuario ) {
this.store.dispatch( new AddUsuario(usuario) );
}
.
.
.
Most helpful comment
The
othersselector re-evaluates when the state changes but because it returns the same value as before the subscription does not fire. The observable has adistinctUntilChangedoperator on it so the same returned value is ignored.The
Object.keys(...)call is returning a new value whenever the selector is re-evaluated which gets through thedistinctUntilChanged. This is why it is different to theothersselector.Hope this answers all your questions ;-)