You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在NgRx Selectors中访问前状态与当前状态?

在NgRx Selectors中访问前后状态的实现方案

默认情况下,NgRx的createSelector只能基于当前状态派生数据,没法直接获取前状态。不过你可以通过两种实用方式实现需求:

方法1:在State中维护前状态副本

把前状态的副本存在store的state结构里,这样就能通过selector同时拿到当前和前状态。

具体示例:

  1. 定义包含前状态的State结构
interface CounterState {
  currentValue: number;
  previousValue: number; // 专门存前一次的状态值
}

const initialState: CounterState = {
  currentValue: 0,
  previousValue: 0,
};
  1. 在Reducer中同步更新前状态
    每次状态变更时,先把当前值转移到previousValue,再更新currentValue:
export function counterReducer(state = initialState, action: CounterActions): CounterState {
  switch (action.type) {
    case '[Counter] Increment':
      return {
        ...state,
        previousValue: state.currentValue,
        currentValue: state.currentValue + 1,
      };
    // 其他action(比如Decrement)同理处理
    default:
      return state;
  }
}
  1. 创建Selector提取前后状态
    用createSelector直接从state中取出两个值并返回:
import { createSelector } from '@ngrx/store';

const selectCounterState = (state: AppState) => state.counter;

export const selectCounterWithPrevious = createSelector(
  selectCounterState,
  (counterState) => ({
    current: counterState.currentValue,
    previous: counterState.previousValue,
  })
);
  1. 在组件中使用
this.store.select(selectCounterWithPrevious).subscribe(({ current, previous }) => {
  console.log(`当前值: ${current}, 前一次值: ${previous}`);
  // 这里可以执行你的推导逻辑,比如计算差值
  const changeAmount = current - previous;
});

方法2:用RxJS的pairwise()操作符

不需要修改state结构,直接在订阅selector时通过pairwise()获取连续的两次状态值(前一次+当前)。

具体示例:

  1. 先创建常规Selector获取当前状态
const selectCurrentCounter = createSelector(
  selectCounterState,
  (counterState) => counterState.currentValue
);
  1. 在组件中通过pairwise()处理
import { pairwise } from 'rxjs/operators';

this.store.select(selectCurrentCounter)
  .pipe(pairwise()) // 每次发射一个数组:[前一次状态, 当前状态]
  .subscribe(([previous, current]) => {
    console.log(`前一次值: ${previous}, 当前值: ${current}`);
    // 执行推导逻辑,比如判断数值变化方向
    const isIncreased = current > previous;
  });

补充:处理初始状态

pairwise()需要至少两次状态发射才会输出结果,如果想第一次状态变更就对比初始值,可以用startWith()补充初始值:

import { pairwise, startWith } from 'rxjs/operators';

this.store.select(selectCurrentCounter)
  .pipe(
    startWith(initialState.currentValue), // 把初始值作为第一个"前状态"
    pairwise()
  )
  .subscribe(([previous, current]) => {
    // 第一次回调时,previous是初始值,current是第一次变更后的值
  });

关于Factory Method

NgRx没有专门提供直接获取前后状态的工厂方法,上述两种是最常用的实现方式。如果需要复用逻辑,你可以自己封装一个高阶函数:

import { Observable } from 'rxjs';
import { pairwise, startWith, map } from 'rxjs/operators';

export function withPrevious<T>(source$: Observable<T>, initialValue: T): Observable<{ previous: T; current: T }> {
  return source$.pipe(
    startWith(initialValue),
    pairwise(),
    map(([previous, current]) => ({ previous, current }))
  );
}

// 使用方式
const counterWithPrevious$ = withPrevious(this.store.select(selectCurrentCounter), initialState.currentValue);
counterWithPrevious$.subscribe(data => { /* 你的处理逻辑 */ });

内容的提问来源于stack exchange,提问作者aravind ks

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 11:47:02