Создать немомоизированный селектор на ngrx

Можно ли создать на ngrx немомоизированный селектор?

У меня есть очень маленький селектор, чтобы проверить, больше ли значение в магазине, чем Date.now ().

export const selectAuthState = createFeatureSelector<AuthState>('auth');
export const hasTimeout = createSelector(
  selectAuthState,
  state => state.timeout < Date.now()
);

Как и ожидалось, этот селектор бесполезен, поскольку он не будет пересчитан, если я не изменю значение timeout. Есть ли способ сделать селектор не запоминающимся, чтобы он пересчитывался каждый раз при обращении к его значению?

Мое текущее решение - создать фабрику селекторов и использовать ее каждый раз, но я не думаю, что это лучшее решение:

export const hasTimeoutFactory = () => createSelector(
  selectAuthStatusState,
  state => state.timeout < Date.now()
);

Другое решение - сделать что-то вроде

export const didTimeout = pipe(
  select(getTimeout), // using memoized value
  map(val => val < Date.now())
);

А потом импортируем эту трубу.


person Alberto Rivera    schedule 19.06.2018    source источник


Ответы (2)


У селектора есть release метод для сброса мемоизации, я думаю, это то, что вы хотели бы использовать.

Это переводится в следующий код:

this.timeout = this.store.pipe(select(hasTimeout));
hasTimeout.release();

Документы

person bobthedeveloper    schedule 24.06.2018
comment
Вероятно, это не сработает, если я не буду выпускать hasTimeout каждый раз, когда использую его, верно? Кроме того, это лучше, чем решение pipe? - person Alberto Rivera; 25.06.2018
comment
да, вам нужно выпускать его каждый раз. Еще одно решение - сохранить дату в вашем магазине. Внутри эффекта вы можете отправить действие, например, для увеличения даты на 1 секунду. - person bobthedeveloper; 26.06.2018
comment
Спасибо за Ваш ответ. Значит, на ngrx нет возможности создать немомоизированный селектор? - person Alberto Rivera; 26.06.2018

У меня была аналогичная проблема, и я сделал следующее - я почти уверен, что это неправильно с точки зрения архитектуры NgRx, но он делает то, что я хочу.

export const selectAuthorizationDetails = createSelector(selectAuthorizationState, 
    (state: AuthorizationState, store: Store<AuthorizationState>) => store,
    (state: AuthorizationState) => new Date(),     // Force the selector memoization to fail which is probably the wrong thing to do
      (state, store, timeNow) => {
        if (state.lastUpdated != null) {
            let diffMs = timeNow.getTime() - state.lastUpdated.getTime()
            if (diffMs > 300000) {
                store.dispatch(refreshAuthorization());
                return null;
            }
            return state.authorizationDetails;
        }
        return null;
      }
  );

В магазине мои данные авторизации хранят время последнего обновления, и поэтому при каждом вызове он проверяет, истек ли срок их действия или нет. Если я использую мемоизацию, это не сработает, и освобождение селектора должно выполняться при каждом вызове, что означает, что мне, вероятно, придется скрыть селектор за фасадом.

При использовании селектора в AuthGuard я просто фильтрую по нулю, чтобы всегда получать самую последнюю версию, но могу кэшировать результаты в течение заранее определенного времени (5 минут в этом примере).

person Scott    schedule 23.10.2019