NGXS selector or Selector annotation return is passing by value or reference?

613 views Asked by At

what is ngxs' way of passing object? I have this following state

@State<CounterStateModel>({
  name: 'counter',
  defaults: { count: 0, isLoading: true, tests: [{value: 0}] }
})

and the selector

@Selector() 
  static count(state: CounterStateModel) {
    return state.count;
  }

  @Selector() 
  static test(state: CounterStateModel) {
    return state.tests;
  }

I used those two selectors in component.ts

  @Select(CounterState.test) test$: Observable<TestModel[]>;
  @Select(CounterState.count) count$: Observable<number>;

then in template I show the value by

<div class="count" *ngFor="let test of (test$ | async)">TEST: {{ test?.value }}</div>
<div class="count">COUNT: {{ (count$ | async) }}</div>

then I increase the count or value by subscribing and directly plus 1

  incrementT() {
    this.test$.subscribe(test => test.map(t => t.value++))
  }

  incrementC() {
    this.count$.subscribe(count => count++)
  }

after clicking button the value in test array element is increased, but count remains the same. so what is NGSX passing? see the stackblitz url:

https://stackblitz.com/edit/ng-ngxs-playground-pmekh1?file=src/app/counter/counter.component.ts

1

There are 1 answers

0
Garth Mason On BEST ANSWER

To mutate values contained in the state you need dispatch an action to the state, rather than modify the values that you receive in your subscriptions.

NGXS enforces this rule to ensure state is immutable, so if in your stack blitz you set developmentMode: true you will see NGXS errors in the console when you try to increment the 'test' values.

enter image description here

To modify the count or the test items you need to dispatch an action to the state and have the state make the update (thus emitting the new value to your subscribed component). This is outlined here in the NGXS documentation. This is a bit of a different way of thinking if you are new to NGXS (or CQRS patterns).