-
-
Notifications
You must be signed in to change notification settings - Fork 2k
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
RFC: feat(selectors): SelectorFactoryWithCache - allow to re-use selectors for props #2104
Comments
@itayod I finally got to write the issue RFC I told you about in Angular-UP...I Would be happy for your input. |
I'm interested in the use case described. |
@timdeschryver If I got it right, the use case here is for caching selectors with params, similar to the memoized selectors and save computation (e.g when the user toggles between layout). |
yes, the selector factory created is used in multiple places in the application - components, services (effects etc) - since it caches the results of calls with params it can eliminate the work when called again with same param.
|
should I open a PR? |
@nadavsinai : If not just the single result for the last supplied state and props were to be cached, but the results for all different props ever evaluated given that same state: How do you intend to prevent unbounded memory consumption? You would need some kind of cache management. By the way, what you suggest sounds pretty much like https://github.com/toomuchdesign/re-reselect in the redux/react ecosystem (whereas the selectors in ngrx seem to be designed like https://github.com/reduxjs/reselect). |
If you want to use the selector at different locations you can use a selector with props. The only difference with your implementation if that it loses its cache if the https://gist.github.com/timdeschryver/43a3337e09a0e1e857d11c317d13439c |
Hi, thanks for your comments. |
both are right. selectors are defined in thier own file and used across the application, but we use createSelectorFactoryWithCache specifically in places where the props are changing (yet in a bounded set of values - eg layout modes) |
Got it, thanks for elaborating @nadavsinai 👍 |
HI, @itayod @timdeschryver @REPLicated |
Thanks for putting in the time by creating a PR. I would suggest to wait now before we take the next steps to make sure this is a good addition to add in |
@nadavsinai thanks for your work on this. I think its an interesting idea, but I also don't know if there is enough value to adding another API for creating selectors. Why wouldn't this just be a guide on creating a cache for selectors with props? We haven't seen enough people with this issue to consider adding this to the API yet. |
When using selectors with object props I'm getting situations where the selector emits multiple times over with actions that don't even modify the selectors states. Everything seems to go back to normal when I put the selector into a factory function as recommended in the docs to improve memoization with selectors that are used with different props. However what I'm seeing is something unexpected even without the factory function. I'm unable to replicate it in a stackblitz as yet... but commenting here in case anyone else has seen something similar. I feel it could be something linked to this issue. https://ngrx.io/guide/store/selectors
|
Going to close this along with the PR for now. We may revisit it at some point. |
Memoized Selectors are a powerful way to wrap computed state logic in a simple yet performant functional casing. We love them.
Selectors with props solve the problem of computing (perhaps expensive) state that relies on runtime supplied values, Howvever when put to test one finds (and can be confused by) the fact that props are checked for referential equality, if the prop type is not scalar (eg object) each new value thrown at the selector will cause all the projection functions to be re-invoked.
Even team members advise to use object props:
#1233 (comment)
which will cause further invocations to loose memoization
And community issues like this arise
#1415
However sometimes the set of runtime values (props) relevant to a computed state is limited, caching selectors for each prop value allows us to keep the memorization and work done in the past.
For example in our medical imaging app we have a grid of canvases, each one has its own state model which is computed by merging few other states. we have a selector that needs the prop of layoutID (identifying that canvas) which is a runtime value, but has limited range. When a user switches layouts or view modes a lot of scripting is happening, we creating the concept of CachedSelectorFactories to reduce some of that scripting time.
The use of the selector from the component/service side is same as selectors without props
this.store.select(selectImageboxModelByLayoutID(layoutID))
but the selector is created by calling this factory function is cached.
the signature of that function is this
whilst that types are:
SelectorFactoryByParams is a factory function creating a selector in the closure of the param.
we only invoke this function if we don't have it cached. I used a Map -> Map<Props, MemoizedSelector<State, Result>> to keep selectors and the release function allows to clear memory when the expected props are not relevant anymore.
The full code is available here , I will open a PR if/when I get positive input on this.
Describe any alternatives/workarounds you're currently using
We have this functionality in an internal lib. It works well for us and allowed us to improve application performance.
If accepted, I would be willing to submit a PR for this feature
[X] Yes (Assistance is provided if you need help submitting a pull request)
Will need guidance with regards to tests you'd like to add and perhaps improve typing.
The text was updated successfully, but these errors were encountered: