- Notifications
You must be signed in to change notification settings - Fork46
Key selectors composition#73
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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
Key selectors composition#73
Uh oh!
There was an error while loading.Please reload this page.
Conversation
coveralls commentedApr 7, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
toomuchdesign commentedApr 7, 2019
Hi@sgrishchenko, I see the point of supporting selectors' composability. I'd like to consider the possibility of providing this feature as an external utility function. Something to directly provide as |
sgrishchenko commentedApr 8, 2019 • edited by toomuchdesign
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by toomuchdesign
Uh oh!
There was an error while loading.Please reload this page.
If I try provide external utility function, I receive something like this: constkeySelector=combineKeySelectors(dependency1,dependency2,(state,props)=>props.someProp)constcachedSelector=createCachedSelector(dependency1,dependency2,(state,props)=>props.someProp,(first,second,someProp)=>({ first, second, someProp}))(keySelector); As you can see, I need again copy-paste dependencies and again so easy when adding a dependency, forget to update key selector. What if I create separate function |
toomuchdesign commentedApr 8, 2019
It seems that the arguments of the hypothetical Not that I like this syntax, but as a proof of concept, might it be expressed like this? constinputSelectors=[dependency1,dependency2,(state,props)=>props.someProp,];constcachedSelector=createCachedSelector(inputSelectors,(first,second,someProp)=>({ first, second, someProp}))(combineKeySelectors(...inputSelectors)); |
sgrishchenko commentedApr 9, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
At first, I can't pass all dependencies in
For this reason, I cannot distinguish state selectors from property selectors and I need do something like this: constkeySelectors=[dependency1,dependency2,(state,props)=>props.someProp,];constcachedSelector=createCachedSelector([state=>state.foo,state=>state.bar, ...keySelectors,],(foo,bar,first,second,someProp)=>({ foo, bar, first, second, someProp}))(combineKeySelectors(...keySelectors)); Secondly, imagine that you future user ofre-reselect library. You have two helpers: Additionally, I understand your concern about granularity of this approach. I suggest to expose two new helper:
What do you think about it? |
toomuchdesign commentedApr 10, 2019
I've personally never dealt with such a scenario, therefore take what I say with a grain of salt: what if It might get cumbersome (wrappers wrapping wrappers... mhh..), but I'd definitely go for thehelper approach. I'd also suggest to find a way ofintroducing these non-core featuregradually: maybe aseparate Same goes for source code and tests: I'd try to keepcore logic and the rest well separated. Rollup will think about shipping all together. If there are still blurry areas about what these utility are supposed to do, we might consider writing down thedocumentation first. Thanks for caring@sgrishchenko! |
toomuchdesign commentedMay 23, 2019
I just sawhttps://github.com/sgrishchenko/reselect-utils! Amazing job, there. I'd keep this issue open as a remainder to update the docs to extensively mention |
toomuchdesign commentedJun 8, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
I'm investigating the feasibility of such an API for the use case@sgrishchenko mentioned: importcreateCachedSelector,{combineKeySelectors}from're-reselect';constcachedSelector=createCachedSelector(dependency1,dependency2,(state,props)=>props.someProp(first,second,someProp)=>({ first, second, someProp}))(combineKeySelectors(options)); If we somehow extended the data provided to the |
toomuchdesign commentedJun 18, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Closing in favour of#78. Thanks@sgrishchenko for the inspiring contribution! |
toomuchdesign commentedJun 22, 2019
Hi@dkaledin@veksa@sv1809@eaglus, With#78 I also tried to provide a So I'm inviting you to provide some real-world examples and possible API's to reason about the possibility of shipping such a Thanks to you all. Cheers! |
mbellman commentedJul 16, 2019 • edited by toomuchdesign
Loading Uh oh!
There was an error while loading.Please reload this page.
edited by toomuchdesign
Uh oh!
There was an error while loading.Please reload this page.
@toomuchdesign@sgrishchenko Interesting following the back-and-forth here. I actually stumbled upon this thread through having misinterpreted the library similarly tothe users in this other thread, and coming to realize that cache key selection didn't follow the mechanism I originally believed. I think some of the frustrations expressed here would be mitigated through a design or option which just provided dependency function results to the cache key selector automatically. This would eliminate redundancies between the 'actual' selector and the cache key selector. Although, maybe this is precisely what@sgrishchenko was alluding to with his It is unfortunate that reselect does not expose itsinternal mechanism for building dependency results as an abstraction, meaning this library would have to replicate that behavior. However, allowing a key selector option to facilitate a predefined, "default" functioncreateDependencyResultsKeySelector(keySelector,dependencies){returnfunction(){constdependencyResults=dependencies.map(dependency=>dependency.apply(null,arguments));returnkeySelector.apply(null,dependencyResults);};}; would allow usage like this: constselectABC=createCachedSelector(selectA,selectB,selectC,(a,b,c)=>compute(a,b,c))((a,b,c)=>`${a}:${b}:${c}`,{useDependencyResults:true});...// BoomselectABC(state); There would of course be (potentially) redundant work between I do want to emphasize the utility of allowing this library to use dependency results, rather than just initial selector arguments, to derive cache keys. It can be unwieldy to have to independently determine and pass in those values in cases where the selectors aren't normally written to take them, just to ensure that I can take advantage of constmapStateToProps=createStructuredSelector({stuff:selectStuff,otherStuff:selectOtherStuff}); ...unless I want to write my key selectors to re-select (hah!) the "dependency results" manually, from I can't see getting around a certain amount of awkwardness either way. For example, this is a little awkward: /** * Using the 'extra argument' form: selectPersonByName(state, 'John') */constselectPersonByName=createCachedSelector(selectPeople,// This 'dependency' just exists to forward the// selector's second argument to the result function(state,name)=>name,(people,name)=>people[name])((_,name)=>name); and this is a little awkward: /** * Using the 'single state argument' form: selectCurrentStudentTestAverage(state) */constselectCurrentStudentTestAverage=createCachedSelector(selectCurrentStudent,// This 'dependency' just exists to forward something// to the key selector (also, let's pretend currentStudent// does not already have the studentId property)selectCurrentStudentId,currentStudent=>{const{ testResults}=currentStudent;returntestResults.reduce((acc,result)=>acc+result,0)/testResults.length;})((_,studentId)=>studentId,{useDependencyResults:true}); Anyway, that's my 2 cents! |
toomuchdesign commentedAug 28, 2019 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Hi@mbellman, I 100% agree that the confusion about what argument are actually received by the As you mentioned, there are a few reasons why
I will openan issue to reason about the opportunity of adding the possibility of providing I'm a bit reluctant to proceed lighthearted for 2 reasons:
But I'm totally curious to better understand whether such a feature could provide real value. |
Uh oh!
There was an error while loading.Please reload this page.
What kind of change does this PR introduce?(Bug fix, feature, docs update, ...)
feature
What is the current behaviour?(You can also link to an open issue here)
Now if you try use cached selectors in dependecies, you need copy-paste all logic from their key selectors.
What is the new behaviour?
In this PR I propose solution for automatic key selectors composition of selector dependecies (will be composed only key selectors which returns strings).
Does this PR introduce a breaking change?(What changes might users need to make in their application due to this PR?)
This PR does not introduce a breaking change but changes some API:
() => ''):like inhere)true)Other information:
When I use cached selector as dependency in simple selector, cached selector invalidates simple selector cache. To fix this I need to make simple selector cached (it is OK) and copy-paste key selector from dependecy (it is not OK). For example:
All this leads to a terrible DX:
If compose key selectors automatically you can rewrite previous example like this:
As result key selector for cachedSelector will be
If you introduce additional props, you can write something like this:
And result key selector again will be composed to this:
Please check if the PR fulfills these requirements: