NgRx中如何让选择器间传递处理后的结果?
问题分析与修改方案
你的代码目前存在两个核心问题:
- 三个子选择器是并列独立执行的,各自直接从原始状态取数据,没有实现“排序结果传给过滤”的链式依赖
- 投影函数完全忽略了前三个选择器的返回值,直接取
state.dataServices,等于前面的排序、过滤逻辑根本没生效
要实现选择器间的结果传递,有两种常用的修改方式:
方式一:嵌套选择器(链式依赖)
先基于原始数据创建排序选择器,再把排序后的结果作为输入传给过滤选择器,最后组合成最终的选择器:
export const selectSortedAndFilteredDataServices = ( selectProperties: SelectProperties, ): MemoizedSelector<AppState, DataService[], DefaultProjectorFn<DataService[]>> => { // 先获取排序后的列表 const sortedSelector = selectSortedDataServices(selectProperties.sort); // 基于排序后的列表创建过滤选择器 const filteredSortedSelector = createSelector( sortedSelector, (sortedData) => selectFilteredDataServices(selectProperties.filter)({ dataServices: sortedData }) ); return filteredSortedSelector; };
注:如果selectFilteredDataServices原本是基于AppState的选择器,需要调整它的输入逻辑,让它能接收包含dataServices的对象(或者直接改成接收数组的纯函数,灵活性更高)。
方式二:在投影函数中分步处理
如果不想嵌套选择器,可以在同一个createSelector的投影函数里,先执行排序,再用排序后的结果执行过滤:
export const selectSortedAndFilteredDataServices = ( selectProperties: SelectProperties, ): MemoizedSelector<AppState, DataService[], DefaultProjectorFn<DataService[]>> => createSelector( selectDataServices, // 只取原始数据一次 (originalData) => { // 第一步:排序原始数据 const sortedData = selectSortedDataServices(selectProperties.sort)({ dataServices: originalData }); // 第二步:用排序后的结果执行过滤 const filteredData = selectFilteredDataServices(selectProperties.filter)({ dataServices: sortedData }); return filteredData; } );
这种方式逻辑更集中,所有处理步骤都在一个投影函数里完成,避免了多层嵌套。
额外优化建议
如果能把selectSortedDataServices和selectFilteredDataServices改造成纯函数(直接接收数组和参数,返回处理后的数组),代码会更简洁易维护:
// 改造后的排序纯函数 const sortDataServices = (data: DataService[], sortConfig: SortConfig): DataService[] => { // 这里写具体排序逻辑 }; // 改造后的过滤纯函数 const filterDataServices = (data: DataService[], filterConfig: FilterConfig): DataService[] => { // 这里写具体过滤逻辑 }; // 最终选择器 export const selectSortedAndFilteredDataServices = ( selectProperties: SelectProperties, ): MemoizedSelector<AppState, DataService[], DefaultProjectorFn<DataService[]>> => createSelector( selectDataServices, (originalData) => { const sorted = sortDataServices(originalData, selectProperties.sort); return filterDataServices(sorted, selectProperties.filter); } );
纯函数的方式更易测试和复用,也能避免选择器上下文的依赖问题。
内容的提问来源于stack exchange,提问作者starcorn
相关产品推荐
相关产品推荐

