-
Notifications
You must be signed in to change notification settings - Fork 666
Update createSelector and defaultMemoize to accept options (maxSize, equalityCheck, resultEqualityCheck)
#513
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
Conversation
Codecov Report
@@ Coverage Diff @@
## master #513 +/- ##
=========================================
Coverage 100.00% 100.00%
=========================================
Files 1 2 +1
Lines 53 94 +41
Branches 7 21 +14
=========================================
+ Hits 53 94 +41
|
4c07b61 to
89ff857
Compare
| (...args: SelectorResultArray<Selectors>) => Result | ||
| ] | ||
| ...items: | ||
| | [...Selectors, (...args: SelectorResultArray<Selectors>) => Result] |
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.
💬 this is so stupid and ugly, but it works (when an optional object at the end of the tuple didn't)
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.
Whoaaa. Don't recall ever seeing : | [ in that order before.
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.
Hah, yeah. My first attempt was just throwing an optional object into the tuple, but that totally broke everything.
I just sort of randomly thought "what if I make it a union of two exact tuples instead", and to my shock and amazement that actually worked. Immediately.
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 really don't need to bother leaving this comment, but for anyone curious, :\n| ...\n| ... is how Typescript does multi-line type-or expressions, just prefix each line with a |. It's like trailing commas in a list.
|
Also just remembered that extracting another file will break the Babel changes I made in the last couple days. Have to compile that file too. |
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.
It kills me to see all those anys in there. But if you're using a single cache structure for multiple Entrys, I guess you just can't know.
Glad to see some of this old code (that still has 44k downloads/month) getting a new lease on life. 👏
| return false | ||
| } | ||
|
|
||
| // Do this in a for loop (and not a `forEach` or an `every`) so we can determine equality as fast as possible. |
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.
Noice!
| (...args: SelectorResultArray<Selectors>) => Result | ||
| ] | ||
| ...items: | ||
| | [...Selectors, (...args: SelectorResultArray<Selectors>) => Result] |
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.
Whoaaa. Don't recall ever seeing : | [ in that order before.
|
Yeah, upon further thought I think I can switch most or all of the The amusing thing is I just copy-pasted the code, and all I had to do was whip up a pair of (helps that the types were really simple in the first place of course, but still neat) |
createSelector now accepts an options object as its last argument.
For now, the only field in that object is `memoizeOptions`. This
field represents whatever the additional parameters are for the
supplied memoization function.
If this options object is supplied, `createSelector`will try to
use the `memoizeOptions` field as the params to `memoize()`. If
the object exists but no `memoizeOptions` field, it will fall back
to whatever memoizer options were passed as args to the original
`createSelectorCreator` call.
Further complicating things: normally, `memoizeOptions` is an array
containing all the individual args. For example, `defaultMemoize`
currently takes one options arg: the `equalityCheck` function used
for comparisons. So, to pass that directly here, you'd do:
createSelector(
[input1, input2],
output,
{ memoizeOptions: [ equalityCheck ] }
)
But, it's very common to want to _only_ use the _first_ options
arg, and many libs have _only_ one arg anyway (like defaultMemoize
does right now). So, to simplify usage, we also allow passing
that first arg directly in `memoizeOptions` without an array
around it:
createSelector(
[input1, input2],
output,
{ memoizeOptions: equalityCheck }
)
Internally, this is done by checking to see if `memoizeOptions` is
an array or not. If it's an array, we use it as-is. If not, we
assume it must be "the first options arg" and wrap it in an array
so it can be spread via `apply()`.
This does mean that a lib that takes an array as its first options
arg will break things here, but I can't immediately see any libs
that do that - most either take `equalityCheck` or an object.
Besides, the goal of this effort is that `defaultMemoize` will
handle enough use cases that's all you'd typically use anyway.
Implementation based on Erik Rasmussen's `lru-memoize`: https://github.com/erikras/lru-memoize
89ff857 to
ee1500d
Compare
|
Replaced a bunch of Also renamed |
| }, | ||
| "dependencies": {} | ||
| "dependencies": { | ||
| "memoize-one": "^6.0.0-beta.1", |
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.
6.0.0 has just been released 🎉
This PR:
createSelectortypes to accept an optional options object as the last argumentmemoizerOptionsfield that exactly matches the type of all of the providedmemoizefunction's arguments after the initial function-to-be-memoized, with exact type inference of all argumentsmemoizerOptionsfield to optionally be just the first of the memoize function's additional arguments, to support the most common cases of configuring a memoize function (such as passing a custom equality comparison function, or whatever options object the memoization lib supports)defaultMemoizeto its own filedefaultMemoizeto accept either of anequalityCheckfunction or an options object as its first argumentdefaultMemoizeto add support for a customizably-sized cache with LRU behavior, based on https://github.com/erikras/lru-memoizeresultCheckEqualitycomparison function to allow reusing the most recent cached value that matches a recalculated value (the "todos.map(todo => todo.id)is still shallow equal after toggling a todo" use case)This makes the following usages possible:
These changes should solve a majority of the complaints users have had with Reselect:
createSelectorCreatorjust to customize the equality comparisonAnd all of this should be entirely backwards-compatible with existing code :)
Example of the latter case from the
defaultMemoizetests: