angular - *ngFor - ngrx aracılığıyla dizi güncellendiğinde DOM'u güncelle


Bir diziden değerleri göstermek için *ngFor kullanıyorum:

[
  {
    id: 1,
    name: 'item1'
  },   
  {
    id: 2,
    name: 'item2'
  }
]

html :

<div *ngFor="let item of (items$ | async); trackBy: trackById;">
   // more html to display data
</div

ts :

items$: Observable<any>;
trackById = trackByProperty('id');

ngOnInit() {
  this.items$ = this.store.pipe(select(selectors.itemsSelector));
}

trackByProperty<T = any>(property: keyof T) {
  return (index: number, object: T) => object[property];
}

Bu amaçlandığı gibi çalışıyor, ngFor items$ array içindeki doğru ve güncel değerleri alıyor

Sorunum, ngrx kullanarak items$ dizisini güncellediğimde, yeni diziyi yakalayamaması ve DOM'u güncelleyememesi.

İşte ngrx kullanarak veri akışı

  1. Diziye eklemek için yeni bir nesne göndererek işlemi (action) reduce ediciye (reducer) gönderin.

      this.store.dispatch(new actions.UpdateArray(
          { id: 3, name: 'item3' }
        )
      );
    
  2. Reducer bu eylemi alır ve store durumunu güncellenmiş dizi ile günceller (yeni öğeyi alır ve diziye ekler).

    case actions.UPDATE_ARRAY: {
      const newItem = action.payload;
      const items = state.items;
      items.push(newItem);
      return {
        ...state,
        items
      };
    }
    
  3. Seçici güncellemeleri.

Reducer'da action.payload'u loglarken state'in doğru şekilde güncellendiğini onaylayabilirim.

Biri, neden *ngFor içinde güncellenmiş bir dizi almadığımı biliyor mu?

Bahsetmeyi unuttum, ama bileşenimde değişiklik algılaması olarak changeDetection: ChangeDetectionStrategy.OnPush kullanıyorum

Güncelle

DOM'un aslında bileşene tıkladığınızda güncellendiğini fark ettim. Bunun için tıklamak zorunda kalmadan güncellenmesini istiyorum.

Cevap #1

Bu, NgRx seçicilerinin bazen istenmeyen davranışa yol açabilen Memoization kullanmasından dolayı olabilir.

Değişiyor

case actions.UPDATE_ARRAY: {
  const newItem = action.payload;
  const items = state.items;
  items.push(newItem);
  return {
    ...state,
    items
  };
}

için

case actions.UPDATE_ARRAY: {
  const newItem = action.payload;
  const items = [...state.items, newItem]; // <-- creates new instance
  return {
    ...state,
    items
  };
}

Sorunu çözmeli.