New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(component-store): add config for debounce selectors #2606
Conversation
f13330b
to
a21ef49
Compare
Preview docs changes for bb376a5 at https://previews.ngrx.io/pr2606-bb376a53/ |
a21ef49
to
15aa810
Compare
249b4fd
to
4eb5600
Compare
4eb5600
to
bb376a5
Compare
R, | ||
ProjectorFn = (...a: unknown[]) => R | ||
>(...args: O): Observable<R> { | ||
const { observables, projector, config } = processSelectorArgs(args); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like that the logic of processSelectorArgs
is extracted 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Tim 😊
debounceSync(), | ||
map((args: any[]) => projector(...args)) | ||
observable$ = combineLatest(observables).pipe( | ||
config.debounce ? debounceSync() : (source$) => source$, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What if we would extract this ternary statement?
Not sure if it's worth it tho, I'm thinking that when this line changes, the line in the if
case would also be changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I couldn't think of a better way to extract it and make it readable/somewhat easier to understand at the same time.
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
By removingdebounceSync
from a single-value selector, the selector value now becomes available immediately after the updates.Longer versions:updates/setState were always syncselectors now fall into two buckets:state selectors likeselector(state => state.foo)
are back to being syncselectors that combine other selectors and/or Observables are still async, scheduled to run into the microtask.Introduce
SelectConfig
configuration for selector. Currently it allows to "debounce" selector values until the state is "settled".By default it will be set to
debounce: false
, as it makes it more predictable (same behaviour as global store) and allows instant reads from the ComponentStore that would return the value synchronously.Why this change?
While having both types of selectors async/debounced by default is more performant, it was also:
This last point became more obvious when I saw effects like:
When
withLatestFrom
is called, theselectedId$
is not ready yet.The obvious alternative solution would be to provide an imperative way to read the data from the ComponentStore - that solution is also planned and will follow this PR.
What is the current behavior?
Closes #
What is the new behavior?
Does this PR introduce a breaking change?
ComponentStore selectors are no longer debounced by default.
Other information