- Notifications
You must be signed in to change notification settings - Fork666
Description
Firstly, I love reselect, it's possibly my favorite part of the redux ecosystem. I love it so much in fact, that I could be accused of overusing selectors - I like to shove as much logic as possible into them, so that my teammates and I can share computed data in a performant way across our app.
Because we rely so heavily on selectors for our logic, selectors are often where our bugs crop up. Redux's debugging tools are excellent, and I'm imagining reselect could pair its debugging tools nicely along with them. A particular emphasis is"No Print Lines". I like that all the information about my app's state store is already present for me to view without a code change. If all the information about the app'scomputed state were available also, I would never have to change my code to figure out what was broken.
Ideas
1. Graph
The first idea is essentially the same as what was originally proposed in#71 : a visual dependency graph of selector parents and children:
(picture grabbed from#71 , originally from@MattSPalmer)
This would be really useful for refactoring heavily depended-on selectors, as well as debugging.
2. Click-to-select
The ability to click a selector on that graph to see what its inputs / outputs are at a given state.
I don't really like the logging solutions in#71 because they don't let you surgically inspect a particular selector without making code changes. Same issue with@ajwhite 'shttps://github.com/ajwhite/reselect-devtools.
Implementation
I don't think it would be too hard to make a drop-in wrapper forcreateSelector which populates the dependency graph:
functioncreateSelector(...dependencies){constresultFunc=dependencies.pop();constselector=Reselect.createSelector(...dependencies,resultFunc);selector.dependencies=dependencies;Redebug.selectorGraph[selector]=selector;returnselector;}
And click-to-select just needsgetState() injected, either via middleware or something even more vanilla:
Redebug.getStateWith(()=>store.getState());
Challenges
Naming
The one thing I am struggling with is getting the selector names. They're usually anonymous! In mycreateSelector wrapper, I'm keying the graph based on theresultFunc'stoString(), which is going to result in pretty ugly display names. For example:
constcurrentUser$=createSelector(ui$,users$,(ui,users)=>users[ui.currentUser]);=>"(ui, users) => users[ui.currentUser]"
A hackish trick that I tried was to name the selectors based onresultFunc's arguments:
constdependencyNames=getParamNames(resultFunc);constselector=createSelector(...dependencies,resultFunc);selector.dependencies=dependencyNames.map((name,i)=>({ name,selector:dependencies[i]}));
But even if I had a perfect argument-name-parsing regex (hard!), it could still break if users used a selector in two places but named its output differently inresultFunc, or if they used object destructuring, or if they uglified their code.
Obviously, we could add string names to the functions but that would add more overhead than I'd like for users of this lib.
[EDIT] Ok, I thought about it for a while and I don't think there's a way to get the names across every environment without writing them explicitly somewhere. I think what I'll do instead is give this lib another function (just one!) called:
Redebug.registerSelectors({selectorName:selector});
This'll be opt-in, otherwise I'll just give the selectors names based on their position in the tree.
Conclusion
- So I'd love to hear if y'all think this is a good idea
- Or if there's some prior work I missed that solves these problems for me
- or if you can help me with my selector name issue.
Thanks for reading!