更新到 Angula v17 后,我正在使用“经典”ngrx(基于可观察值)和新的 ngrx/signals 存储重写遗留组件。
我按以下方式定义了一些选择器:
withComputed((state) => ({
selectOrderId: computed(() => state.orderId()),
selectAvailableAgents: computed(() => state.availableAgents())
...
})
但是,由于信号的lazy性质,如果我在组件类(而不是模板)中使用这些选择器,那么如果值发生变化,它们将不会动态更新:
const orderId = this.ordersStore.selectOrderId();
// orderId has only the current (at the time of invocation) value from the store
如果
orderId
为空,我需要调用服务来获取它,将值返回给组件并更新存储。最终,为了将这个逻辑保持在一起,我可以在 withMethod
中实现这个逻辑,返回值作为可观察值。 withMethods((state, ordersService = inject(OrdersService)) => ({
fetchOrderId$: () => {
const orderId = state.orderId();
// If orderId available, do not call the API
if (orderId) {
return of(orderId);
}
return ordersService.getOrderId()
.pipe(
tapResponse({
next: (orderId) => {
patchState(state, { orderId })
},
error: (error: HttpErrorResponse) => {
console.error("An error occurred: ", error.message);
}
})
)
}
//In component class:
this.orderStore.fetchOrderId$()
.pipe(
takeUntil(this.destroy$)
)
.subscribe({
next: (orderId) => {
// Here the logic using orderId
}
)}
但是,使用这种方法似乎有点破坏了信号的工作方式。
在这种情况下,我可以将
effect()
视为间接检测信号状态的特定部分何时更改并向组件应用特定操作的唯一方法。但 Angular 文档建议不要使用它们来传播状态,以避免潜在的问题。对于不需要立即获取值的情况,我将使用
rxMethods
来更新状态并在参数发生变化时重新执行。
这是使用 ngrx 信号管理选择器和值的有效方法还是我遗漏了什么?
只是为了确保您没有犯我所犯的同样错误: 当您从信号存储中选择信号时,不要调用它(即添加
()
)。如果这样做,信号只会被评估一次,并且您没有信号的句柄,但有该信号中的任何值。
您应该仅在真正需要该值时调用/评估信号。例如在你的html中,如果你想显示当前值