首页 > 解决方案 > *ngFor - 通过 ngrx 更新数组时更新 dom

问题描述

我正在使用 *ngFor 来显示数组中的值:

[
  {
    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];
}

这按预期工作,ngFor 在items$ array

我的问题是,当我items$使用它更新数组时,ngrx它似乎没有捕捉到新数组并且没有更新 DOM

继承人的数据流使用ngrx

  1. 向 reducer 发送操作,发送一个新对象以添加到数组中。

      this.store.dispatch(new actions.UpdateArray(
          { id: 3, name: 'item3' }
        )
      );
    
  2. Reducer 接收此操作并使用更新的数组更新存储状态(接收新项目并将其推送到数组)。

    case actions.UPDATE_ARRAY: {
      const newItem = action.payload;
      const items = state.items;
      items.push(newItem);
      return {
        ...state,
        items
      };
    }
    
  3. 选择器更新。

在reducer中注销action.payload时,我可以确认状态得到正确更新。

有谁知道为什么我没有得到更新的数组*ngFor

忘了提,但我changeDetection: ChangeDetectionStrategy.OnPush在我的组件中用作我的更改检测

更新

我发现当你点击组件时 DOM 实际上会更新。我希望它无需这样做即可更新。

标签: angulartypescriptrxjs

解决方案


这可能是因为 NgRx 选择器使用了记忆化,这有时会导致不良行为。

改变

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

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

应该解决问题。


推荐阅读