ค้นหาเว็บไซต์

javascript - การสมัครวันที่จะถูกกระตุ้นเมื่อส่วนอื่นของ state เปลี่ยนใน ngrx


ฉันมีคุณสมบัติ start และ end ซึ่งเก็บวันที่ใน state ของฉัน ทุกครั้งที่ส่วนอื่นของ state ถูกเปลี่ยน การ subscription ของฉันสำหรับวันที่ start และ end จะถูกเรียกใช้

นี่คือการสมัครสมาชิกของฉัน

this.subs.sink = this.store
      .select(fromTransactionReducer.selectStartAndEndDate)
      .subscribe((date) => {
        console.log("range", date);
        this.range.setValue({
          start: date.start,
          end: date.end,
        });
      });

นี่คือตัวเลือก

export const selectStartAndEndDate = createSelector(
  selectTransactionState,
  (state) => ({ start: state.start, end: state.end })
);

นี่คือตัวลด dateRange

  on(transactionActions.UpdateDateRange, (state, { start, end }) => ({
    ...state,
    start,
    end,
  })),

นี่คือช่วงวันที่ของการกระทำ

export const UpdateDateRange = createAction(
  "[Transaction Page] Update Date Range",
  props<{ start: Date; end: Date }>()
);

นี่คือรัฐของฉัน

export interface State {
  transaction: Transaction[];
  cursors: Cursor;
  totalTransactions: number;
  loading: boolean;
  errorMessage: string;
  formErrorMessage: string;
  items_per_page: number;
  pageSizeOptions: number[];
  pageIndex: number;
  searchKey: string;
  formMessage: string;
  start: Date;
  end: Date;
  trans_type: string;
  base_type: string;
}
export const initialState: State = {
  transaction: [],
  cursors: {
    after: "",
    before: "",
    hasNext: false,
    hasPrevious: false,
  },
  totalTransactions: 0,
  loading: false,
  errorMessage: null,
  formErrorMessage: null,
  items_per_page: 5,
  pageSizeOptions: [2, 3, 5, 10, 15],
  pageIndex: 0,
  searchKey: "",
  formMessage: "",
  start: null,
  end: null,
  trans_type: null,
  base_type: null,
};

ทุกครั้งที่ฉันส่ง action ที่แตกต่างกัน เช่น this.store.dispatch(transactionActions.ResetPageIndex()); subscription ของฉันสำหรับวันที่จะถูกเรียกใช้งาน

ทำไมถึงเป็นอย่างนั้น ? :

ใน reducer ของฉัน ฉันจะอัปเดตเฉพาะวันที่ start และ end เมื่อมีการส่ง action UpdateDateRange

คำตอบ #1

โอเปอเรเตอร์ select ของ ngrx ใช้โอเปอเรเตอร์ distinctUntilChanged ของ rxjs เพื่อให้มั่นใจว่าสเลกเตอร์จะปล่อยค่าออกมาเฉพาะเมื่อผลลัพธ์ของมันมีการเปลี่ยนแปลง ดูโค้ดต้นฉบับได้ที่นี่: https://github.com/ngrx/platform/blob/a6fe92df3134b7a589a2e95abe0aea183b411f03/modules/store/src/store.ts#L249

โดยค่าเริ่มต้น distinctUntilChanged จะใช้ตัวเปรียบเทียบความเท่าเทียมกัน (ดูที่ https://www.learnrxjs.io/learn-rxjs/operators/filtering/distinctuntilchanged) และสังเกตว่า 'การอ้างอิงวัตถุต้องตรงกัน!'

ตอนนี้มาที่ตัวเลือก selectStartAndEndDate ของคุณ - มันจะส่งกลับ วัตถุ

นอกจากนี้ มันยังส่งกลับ อินสแตนซ์ใหม่ ของวัตถุทุกครั้งที่ทำงาน เนื่องจากเหตุนี้ การเปรียบเทียบใน distinctUntilChanged จึงล้มเหลวเสมอ ทำให้ตัวเลือกส่งค่าอยู่ตลอด

วิธีแก้ไข:

// returned date will be considered equal next time so selector won't fire
export const selectStartDate = createSelector(
  selectTransactionState,
  (state) => state.start
);

// same here
export const selectEndDate = createSelector(
  selectTransactionState,
  (state) => state.end
);

// as input selectors didn't change, this won't fire either
export const selectStartAndEndDate = createSelector(
  selectStartDate,
  selectEndDate ,
  (start, end) => ({ start, end })
);

Stackblitz: https://codesandbox.io/s/so-ngrx-selector-emit-1zxg1?file=/src/app/store/selectors.ts