问题
Is it possible to create a non-memoized selector on ngrx?
I have a very small selector to check whether a value in the store is greater than Date.now().
export const selectAuthState = createFeatureSelector<AuthState>('auth');
export const hasTimeout = createSelector(
selectAuthState,
state => state.timeout < Date.now()
);
As expected, this selector is not useful since it won't be recalculated unless I change the value of timeout
. Is there any way to make the selector non-memoized, so that it is recalculated every single time its value is accessed?
My current solution is creating a selector factory and using it every time, but I don't think it is the best solution:
export const hasTimeoutFactory = () => createSelector(
selectAuthStatusState,
state => state.timeout < Date.now()
);
Another solution would be doing something like
export const didTimeout = pipe(
select(getTimeout), // using memoized value
map(val => val < Date.now())
);
And then importing this pipe.
回答1:
A selector has a release
method to reset the memoization, I think this is what you'd want to use.
This translates in the following code:
this.timeout = this.store.pipe(select(hasTimeout));
hasTimeout.release();
Docs
回答2:
I had a similar issue and did the following - I'm fairly sure it is wrong in terms of NgRx architecture but it does what I want it to do.
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;
}
);
In the store my authorization details store the last updated time and so on each invocation, it tests whether they've expired or not. If I use memoization then it won't work and releasing the selector then has to be done on each call meaning I'd probably need to hide the selector behind a facade.
When using the selector in an AuthGuard, I simply filter on null so that I can always get the most up to date version but can cache the results for a pre-determined time (5 mins in this example)
来源:https://stackoverflow.com/questions/50920308/create-non-memoized-selector-on-ngrx