如何将两个不同状态的动态Selector组合为新Selector?
问题解答
首先明确:你尝试的那种直接嵌套调用Selector的写法不可行。
原因在于NgRx的@Selector装饰器(或createSelector函数)的依赖参数,要求是「指向状态切片的Selector实例」或状态路径,而不是另一个Selector执行后的结果。你写的OrderState.orderFilteredByStatus(DashboardState.status("fixedName")),本质是试图把一个Selector的运行结果作为参数传入另一个Selector工厂函数,但Selector的执行是NgRx在状态变更时自动触发的,定义阶段根本无法获取到DashboardState.status("fixedName")的实际值。
正确的组合方式
要实现你想要的逻辑——用固定name获取到的status值来过滤订单,有两种清晰的实现方式:
方式1:抽离公共逻辑,合并到新Selector
先把orderFilteredByStatus里的过滤逻辑抽成独立函数,然后在新Selector中同时依赖两个原始Selector,结合结果完成过滤:
// 抽离公共过滤逻辑,让两个Selector复用 private static filterOrdersByStatus(state: OrderStateModel, status: string): Order[] { // 原orderFilteredByStatus中的过滤逻辑,比如: return state.orders.filter(order => order.status === status); } // 原orderFilteredByStatus改成复用这个函数 static orderFilteredByStatus(status: string){ return createSelector([OrderState], (state: OrderStateModel) => { return this.filterOrdersByStatus(state, status); }); } // 组合后的新Selector @Selector([DashboardState.status("fixedName"), OrderState]) static ordersDashboard(status: string, orderState: OrderStateModel): Order[] { return this.filterOrdersByStatus(orderState, status); }
方式2:嵌套创建Selector
如果不想抽离逻辑,也可以通过嵌套createSelector来实现,先获取status值,再基于该值创建过滤订单的Selector:
static ordersDashboard() { return createSelector( // 先获取固定name对应的status DashboardState.status("fixedName"), // 用获取到的status创建过滤订单的Selector (status) => createSelector(OrderState, (state) => { // 直接写过滤逻辑,或者调用原orderFilteredByStatus的逻辑 return state.orders.filter(order => order.status === status); }) ); }
不过这种方式返回的是一个高阶Selector,使用时需要额外处理,不如第一种方式直观。
补充说明
你提到的switchMap()是用于在Observable流中组合,但对于纯Selector的组合,上面的方式更符合NgRx的设计范式,避免引入不必要的流操作。
内容的提问来源于stack exchange,提问作者Invader
相关产品推荐
相关产品推荐

