-
Notifications
You must be signed in to change notification settings - Fork 1
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
Parameterized selectors #1
Comments
Sorry, I missed this notification. Something like this: const selectUserById = makeParameterizedSelector('selectUserById', userId => {
return query => {
return query(state => state.users[id])
}
}) The selector can be used like this: selectUserById(1)(state)
selectUserById(2)(state)
selectUserById(3)(state) with the property that identity is preserved: selectUserById(1) === selectUserById(1) // returns the same function instance |
Hey @dtinth, what do you think about including the definition of |
const key = args.join(',') However, I don't think this is safe because not all arguments can be uniquely stringified: [{ a: 1 }, { b: 1 }].join(',')
// => "[object Object],[object Object]" For this reason I wonder whether it would be better for function select(state: State, ...extraParams: ExtraParams): Result {
if (cachedResult) {
+ // Check if extra params have changed
+ let changed = false
+ for (const [index, value] of cachedResult.extraParams.entries()) {
+ if (extraParams[index] === value) {
+ changed = true
+ }
+ }
// Check if dependencies changed
for (const [selector, value] of cachedResult.dependencies.entries()) {
if (selector(state, ...extraParams) !== value) {
changed = true
reason = selector
break
}
}
}
} const selectUserById = makeSelector((query, userId) => {
return query(state => state.users[id])
})
selectUserById(state, myUserId); This also means users could use WDYT @dtinth? |
@OliverJAsh Thanks for your opinion! Sorry, I missed the notification, that’s why it took me so long to reply. Feel free to ping me on Twitter (@dtinth). Yes I agree having
So for this project, flexibility comes over convenience. I would be very happy if someone makes a higher-level library that makes use-cases such as parameterized selectors more convenient. In reply to your proposal,
|
Thanks for the reply @dtinth!
Isn't the solution to this to use factories, e.g. so we can have one selector instance per component? E.g. in reselect: const makeSelectUserById = () => createSelector(
getUsersById,
(state, userId) => userId,
(users, id) => {
return users[id]
}
)
const selectUserById1 = makeSelectUserById(); // this has its own cache
const selectUserById2 = makeSelectUserById(); // this has its own cache We could use the same idea with my proposal above: const makeSelectUserById = () => makeSelector((query, userId) => {
return query(state => state.users[id])
})
const selectUserById1 = makeSelectUserById(); // this has its own cache
const selectUserById2 = makeSelectUserById(); // this has its own cache In that case, if a selector receives a different argument, then we deliberately want to recompute.
Wow, I'd love to hear more about this, because currently we have little visibility over how well our selectors are memoized, which in turn means we have little visibility over how efficient/inefficient our React re-renders are. Are you able to share any more information about the setup you have? |
@OliverJAsh Factories is one solution but the lifetime the selector-cache depends on the lifecycle of the component that uses it. Global memoization vs per-component memoization (factories)Consider a fictional case in a project management app where we need a selector, parameterized by project ID, that takes the following input selectors:
and outputs a summary of suggestions to users what they should focus on today. If this selectors happens to be used by 2 components, then this summary must be computed twice each time the store is updated. That’s why we create a global memoization-cache instead, which is what const selectSummaryByProjectId = _.memoize((projectId: string) => {
return makeSelector(query => {
// ...
})
}) Now, multiple components that uses the same The drawback is that without a memoization-cache eviction strategy, this global memoization-cache will keep growing as more distinct
To summarize,
So that’s why I did not include it in the library. React-Redux-rereselect integrationThe basic flow is this:
Here’s how we tie 4 back to 2 (and sometimes 1):
|
Can you please provide me with an example of how you are using the function provided? I am struggling to infer usage, and it doesnt appear to be anywhere within your tests etc.
Thanks :)
The text was updated successfully, but these errors were encountered: