-
Notifications
You must be signed in to change notification settings - Fork 675
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
Update createSelector and defaultMemoize
to accept options (maxSize, equalityCheck, resultEqualityCheck)
#513
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 any
s in there. But if you're using a single cache structure for multiple Entry
s, 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 |
@@ -110,5 +110,8 @@ | |||
"ts-jest": "26.5.6", | |||
"typescript": "^4.4.0" | |||
}, | |||
"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:
createSelector
types to accept an optional options object as the last argumentmemoizerOptions
field that exactly matches the type of all of the providedmemoize
function's arguments after the initial function-to-be-memoized, with exact type inference of all argumentsmemoizerOptions
field 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)defaultMemoize
to its own filedefaultMemoize
to accept either of anequalityCheck
function or an options object as its first argumentdefaultMemoize
to add support for a customizably-sized cache with LRU behavior, based on https://github.com/erikras/lru-memoizeresultCheckEquality
comparison 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:
createSelectorCreator
just to customize the equality comparisonAnd all of this should be entirely backwards-compatible with existing code :)
Example of the latter case from the
defaultMemoize
tests: