选择器啥时候执行? ngxs

Posted

技术标签:

【中文标题】选择器啥时候执行? ngxs【英文标题】:When do selectors execute? ngxs选择器什么时候执行? ngxs 【发布时间】:2019-07-16 04:43:01 【问题描述】:

现场演示https://stackblitz.com/edit/angular-vw78jf

在我的 ngxs 状态中有 ToppingsStateModel

export interface ToppingsStateModel 
  entities:  [ id: number ]: Topping ;
  selectedToppings: number[];

一个操作更改了我的实体列表,另一个操作更改了 selectedToppings。 在 products.component 我从选择器中获取浇头列表

export class ToppingsState 
  constructor(private toppingsService: ToppingsService) 
  

  @Selector()
  static entities(state: ToppingsStateModel) 
    console.log('getEntities', state.entities);
    return state.entities;
  

  @Selector([ToppingsState.entities])
  static toppings(state: ToppingsStateModel, entities: [id: number]: Topping): Topping[] 
    return Object.keys(entities).map(id => entities[parseInt(id, 10)]);
  
 ...

它是product.component

export class ProductsComponent implements OnInit 

  @Select(ToppingsState.toppings) toppings$: Observable<Topping[]>;

  constructor(private store: Store, private actions$: Actions) 

  ngOnInit() 
    const state = this.store.dispatch(new LoadToppings());
    setTimeout(() => this.store.dispatch(new VisualizeToppings([1])), 2000);
    this.toppings$.subscribe((toppings) => console.log('UUUU NEW TOPPINGS!!!'));
  

当我调度 VisualizeToppings 操作时,我会得到新的 toppings 值。在我的控制台中,我有

action [Products] Load Toppings @ 10:57:59.735
getEntities 
UUUU NEW TOPPINGS!!!
getEntities 1: …, 2: …
UUUU NEW TOPPINGS!!!
action [Products] Visualize Toppings @ 10:58:01.744
getEntities 1: …, 2: …
UUUU NEW TOPPINGS!!!

我改变了状态的另一部分。当我调度 VisualizeToppings 操作时,为什么选择器会再次执行?我做错了什么?

【问题讨论】:

从内存中我认为自定义选择器在每次状态更改时都会执行 - 在文档中找不到这个,但我可能已经在 NGXS github 或 slack 频道中阅读过它。我认为你没有做任何“错误”导致这种情况发生。 出于兴趣而不是静态选择器,如果您直接订阅会发生什么?例如@Select(state => state.toppings.entities) toppings$ .. 直接订阅有效 O_o 但我认为这是解决问题的坏方法。附:在 NGRX 中一切正常,当我使用 createSelector 【参考方案1】:

@Selector 存在一个已知问题,容器状态类的模型始终假定为第一个参数。见:https://github.com/ngxs/store/issues/386#issuecomment-395780734

这是您的问题...由于第一个参数,您的选择器依赖于状态模型ToppingsStateModel 和指定的ToppingsState.entities 选择器。

  @Selector([ToppingsState.entities])
  static toppings(state: ToppingsStateModel, entities: [id: number]: Topping): Topping[] 
    return Object.keys(entities).map(id => entities[parseInt(id, 10)]);
  

这会导致在 ToppingsStateModel 的任何部分发生更改时重新计算选择器。作为一种解决方法,您可以将选择器移动到不是 State 类的另一个类并删除第一个参数。我将这些称为查询类。这被称为元选择器,请参阅此处的文档:https://ngxs.gitbook.io/ngxs/concepts/select#meta-selectors

这将作为 NGXS v4 中的重大更改的一部分进行修复(请参阅https://github.com/ngxs/store/issues/827),目前有一个 PR 用于在 NGXS v4 到来之前更改此行为的功能标志。见:https://github.com/ngxs/store/pull/858

我希望这有助于并解释问题。

【讨论】:

感谢@Mark Whitield 的官方回答 谢谢你帮助理解

以上是关于选择器啥时候执行? ngxs的主要内容,如果未能解决你的问题,请参考以下文章

我们应该取消订阅 ngxs Selector 吗?

alt+f4无法关闭此窗口,如何解决?我说的是快捷键关闭此窗口,不要告诉我点击确定、任务管理器啥的!

从状态中抽象选择器和动作处理程序

Angular 5:NGXS 和路由解析器

如何将 NGXS 与路由解析器一起使用?

是否可以在状态 B 的选择器内使用来自状态 A 的数据?