Skip to content

Commit

Permalink
Merge 2d0ca70 into a13d01e
Browse files Browse the repository at this point in the history
  • Loading branch information
toomuchdesign committed Feb 3, 2019
2 parents a13d01e + 2d0ca70 commit bddd82e
Show file tree
Hide file tree
Showing 6 changed files with 39 additions and 29 deletions.
9 changes: 9 additions & 0 deletions .all-contributorsrc
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,15 @@
"code",
"test"
]
},
{
"login": "augnustin",
"name": "Augustin Riedinger",
"avatar_url": "https://avatars3.githubusercontent.com/u/1970156?v=4",
"profile": "https://augustin-riedinger.fr",
"contributions": [
"ideas"
]
}
],
"repoType": "github"
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
- Update TypeScript typings
- Introduce typings for heterogeneous selectors
- Introduce typings for any number of uniform selectors
- Rename "resolver" as "keySelector"

### New Features

Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ const cachedSelector = createCachedSelector(
// resultFunc
(A, B) => expensiveComputation(A, B)
)(
// resolverFunction
// keySelector
// Instruct re-reselect to use "itemName" as cacheKey
(state, itemName) => itemName
);
Expand Down Expand Up @@ -75,8 +75,8 @@ const fooResultAgain = cachedSelector(state, 'foo');
- [How do I test a re-reselect selector?](#how-do-i-test-a-re-reselect-selector)
- [Testing `reselect` selectors stored in the cache](#testing-reselect-selectors-stored-in-the-cache)
- [API](#api)
- [reReselect([reselect's createSelector arguments])(resolverFunction, { cacheObject, selectorCreator })](#rereselectreselects-createselector-argumentsresolverfunction--cacheobject-selectorcreator)
- [resolverFunction](#resolverfunction)
- [reReselect([reselect's createSelector arguments])(keySelector, { cacheObject, selectorCreator })](#rereselectreselects-createselector-argumentskeyselector--cacheobject-selectorcreator)
- [keySelector](#keyselector)
- [options.cacheObject](#optionscacheobject)
- [Custom cache strategy object](#custom-cache-strategy-object)
- [options.selectorCreator](#optionsselectorcreator)
Expand Down Expand Up @@ -122,9 +122,9 @@ What happens, here? `getPieceOfData` **selector cache is invalidated** on each c

`cacheKey` is by default a `string` or `number` but can be anything depending on the chosen cache strategy (see [`cacheObject` option](#optionscacheobject)).

`cacheKey` is the output of `resolverFunction`, declared at selector initialization.
`cacheKey` is the output of `keySelector`, declared at selector initialization.

`resolverFunction` is a **custom function** which:
`keySelector` is a **custom function** which:

- takes the same arguments as the final selector (in the example: `state`, `itemId`, `'dataX'`)
- returns a `cacheKey`.
Expand All @@ -149,7 +149,7 @@ const getPieceOfData = createCachedSelector(

But now, **each time the selector is called**, the following happens behind the scenes:

1. **Evaluate the `cacheKey`** for current call by executing `resolverFunction`
1. **Evaluate the `cacheKey`** for current call by executing `keySelector`
2. **Retrieve** from cache the **`reselect` selector** stored under the given `cacheKey`
3. **Return found selector or create a new one** if no selector was found
4. **Call returned selector** with provided arguments
Expand Down Expand Up @@ -198,7 +198,7 @@ export const getMyData = createSelector(
);
```

...add `resolverFunction` in the second function call:
...add `keySelector` in the second function call:

<!-- prettier-ignore -->
```js
Expand All @@ -222,9 +222,9 @@ const myData = getMyData(state, 'foo', 'bar');

### How do I use multiple inputs to set the cacheKey?

`cacheKey` is the return value of `resolverFunction`.
`cacheKey` is the return value of `keySelector`.

`resolverFunction` receives the same arguments of your `inputSelectors` and (by default) **must return a `string` or `number`.**
`keySelector` receives the same arguments of your `inputSelectors` and (by default) **must return a `string` or `number`.**

A few good examples and [a bonus](https://github.com/toomuchdesign/re-reselect/issues/3):

Expand Down Expand Up @@ -319,20 +319,20 @@ import reReselect from 're-reselect';
import createCachedSelector from 're-reselect';
```

### reReselect([reselect's createSelector arguments])(resolverFunction, { cacheObject, selectorCreator })
### reReselect([reselect's createSelector arguments])(keySelector, { cacheObject, selectorCreator })

**Re-reselect** accepts reselect's original [`createSelector` arguments][reselect-create-selector] and returns a new function which accepts **2 arguments**:

- `resolverFunction`
- `keySelector`
- `options { cacheObject, selectorCreator }` _(optional)_

#### resolverFunction
#### keySelector

`resolverFunction` is a custom function receiving the same arguments as your selectors (and `inputSelectors`) and **returning a `cacheKey`**.
`keySelector` is a custom function receiving the same arguments as your selectors (and `inputSelectors`) and **returning a `cacheKey`**.

`cacheKey` is **by default a `string` or `number`** but can be anything depending on the chosen cache strategy (see [`cacheObject` option](#optionscacheobject)).

The `resolverFunction` idea comes from [Lodash's .memoize][lodash-memoize].
The `keySelector` idea comes from [Lodash's .memoize][lodash-memoize].

#### options.cacheObject

Expand All @@ -358,7 +358,7 @@ import createCachedSelector, {LruObjectCache, LruMapCache} from 're-reselect';
createCachedSelector(
// ...
)(
resolverFunction,
keySelector,
{
cacheObject: new LruObjectCache({cacheSize: 5}),
// or:
Expand Down Expand Up @@ -441,12 +441,12 @@ Reset `recomputations` count.
Thanks to you all ([emoji key][docs-all-contributors]):

<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->

<!-- prettier-ignore -->
| [<img src="https://avatars3.githubusercontent.com/u/4573549?v=4" width="100px;"/><br /><sub><b>Andrea Carraro</b></sub>](http://www.andreacarraro.it)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign "Code") [📖](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign "Documentation") [🚇](#infra-toomuchdesign "Infrastructure (Hosting, Build-Tools, etc)") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=toomuchdesign "Tests") [👀](#review-toomuchdesign "Reviewed Pull Requests") | [<img src="https://avatars2.githubusercontent.com/u/830824?v=4" width="100px;"/><br /><sub><b>Stepan Burguchev</b></sub>](https://github.com/xsburg)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=xsburg "Code") [👀](#review-xsburg "Reviewed Pull Requests") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=xsburg "Tests") | [<img src="https://avatars3.githubusercontent.com/u/693493?v=4" width="100px;"/><br /><sub><b>Mitch Robb</b></sub>](https://olslash.github.io/)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=olslash "Code") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=olslash "Tests") | [<img src="https://avatars3.githubusercontent.com/u/1128559?v=4" width="100px;"/><br /><sub><b>Stephane Rufer</b></sub>](https://github.com/rufman)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=rufman "Code") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=rufman "Tests") | [<img src="https://avatars0.githubusercontent.com/u/2788860?v=4" width="100px;"/><br /><sub><b>Tracy Mullen</b></sub>](https://github.com/spiffysparrow)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=spiffysparrow "Code") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=spiffysparrow "Tests") | [<img src="https://avatars1.githubusercontent.com/u/4211838?v=4" width="100px;"/><br /><sub><b>Sushain Cherivirala</b></sub>](https://www.skc.name)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=sushain97 "Code") | [<img src="https://avatars0.githubusercontent.com/u/6316590?v=4" width="100px;"/><br /><sub><b>Steve Mao</b></sub>](https://twitter.com/MaoStevemao)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=stevemao "Documentation") |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| [<img src="https://avatars2.githubusercontent.com/u/1428826?v=4" width="100px;"/><br /><sub><b>Gaurav Lahoti</b></sub>](https://github.com/Dante-101)<br />[🐛](https://github.com/toomuchdesign/re-reselect/issues?q=author%3ADante-101 "Bug reports") | [<img src="https://avatars3.githubusercontent.com/u/13602053?v=4" width="100px;"/><br /><sub><b>Lon</b></sub>](http://lon.im)<br />[🐛](https://github.com/toomuchdesign/re-reselect/issues?q=author%3Acnlon "Bug reports") | [<img src="https://avatars2.githubusercontent.com/u/5492495?v=4" width="100px;"/><br /><sub><b>bratushka</b></sub>](https://github.com/bratushka)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=bratushka "Code") | [<img src="https://avatars3.githubusercontent.com/u/615381?v=4" width="100px;"/><br /><sub><b>Anders D. Johnson</b></sub>](https://andrz.me)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=AndersDJohnson "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/8556724?v=4" width="100px;"/><br /><sub><b>Július Retzer</b></sub>](https://github.com/wormyy)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=wormyy "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/10407025?v=4" width="100px;"/><br /><sub><b>Maarten Schumacher</b></sub>](https://github.com/maartenschumacher)<br />[🤔](#ideas-maartenschumacher "Ideas, Planning, & Feedback") | [<img src="https://avatars2.githubusercontent.com/u/664238?v=4" width="100px;"/><br /><sub><b>Alexander Jarvis</b></sub>](https://github.com/alexanderjarvis)<br />[🤔](#ideas-alexanderjarvis "Ideas, Planning, & Feedback") |
| [<img src="https://avatars1.githubusercontent.com/u/514026?v=4" width="100px;"/><br /><sub><b>Gregg B</b></sub>](https://github.com/greggb)<br />[💡](#example-greggb "Examples") | [<img src="https://avatars0.githubusercontent.com/u/897931?v=4" width="100px;"/><br /><sub><b>Ian Obermiller</b></sub>](http://ianobermiller.com)<br />[👀](#review-ianobermiller "Reviewed Pull Requests") | [<img src="https://avatars3.githubusercontent.com/u/7040242?v=4" width="100px;"/><br /><sub><b>Kanitkorn Sujautra</b></sub>](https://github.com/lukyth)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=lukyth "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/6233440?v=4" width="100px;"/><br /><sub><b>Brian Kraus</b></sub>](https://github.com/suark)<br />[📖](https://github.com/toomuchdesign/re-reselect/commits?author=suark "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/9800850?v=4" width="100px;"/><br /><sub><b>Mateusz Burzyński</b></sub>](https://github.com/Andarist)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=Andarist "Code") [🚇](#infra-Andarist "Infrastructure (Hosting, Build-Tools, etc)") | [<img src="https://avatars1.githubusercontent.com/u/7252227?v=4" width="100px;"/><br /><sub><b>el-dav</b></sub>](https://github.com/el-dav)<br />[🐛](https://github.com/toomuchdesign/re-reselect/issues?q=author%3Ael-dav "Bug reports") | [<img src="https://avatars3.githubusercontent.com/u/15995890?v=4" width="100px;"/><br /><sub><b>Sergei Grishchenko</b></sub>](https://github.com/sgrishchenko)<br />[💻](https://github.com/toomuchdesign/re-reselect/commits?author=sgrishchenko "Code") [⚠️](https://github.com/toomuchdesign/re-reselect/commits?author=sgrishchenko "Tests") |
| [<img src="https://avatars3.githubusercontent.com/u/1970156?v=4" width="100px;"/><br /><sub><b>Augustin Riedinger</b></sub>](https://augustin-riedinger.fr)<br />[🤔](#ideas-augnustin "Ideas, Planning, & Feedback") |

<!-- ALL-CONTRIBUTORS-LIST:END -->

Expand Down
8 changes: 4 additions & 4 deletions src/__tests__/index.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,24 @@ beforeEach(() => {

function selectorWithMockedResultFunc() {
return createCachedSelector([], resultFuncMock)(
(arg1, arg2) => arg2 // Resolver
(arg1, arg2) => arg2 // keySelector
);
}

describe('createCachedSelector', () => {
describe('"recomputations" property and cached selectors', () => {
describe('Resolver returns the same value', () => {
describe('keySelector returns the same value', () => {
it('Should create and use the same cached selector', () => {
const cachedSelector = selectorWithMockedResultFunc();
const firstCall = cachedSelector('foo', 'bar');
const secondCallWithSameResolver = cachedSelector('foo', 'bar');
const secondCallWithSamekeySelector = cachedSelector('foo', 'bar');

expect(createSelectorSpy).toHaveBeenCalledTimes(1);
expect(cachedSelector.recomputations()).toBe(1);
});
});

describe('Resolver returns 2 different values', () => {
describe('keySelector returns 2 different values', () => {
it('Should create 2 selectors only and produce 2 recomputations', () => {
const cachedSelector = selectorWithMockedResultFunc();
const firstCallResult = cachedSelector('foo', 'bar');
Expand Down
8 changes: 4 additions & 4 deletions src/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ export type ParametricSelector<S, P, R> = (
...args: any[]
) => R;

export type Resolver<S> = (state: S, ...args: any[]) => any;
export type ParametricResolver<S, P> = (
export type KeySelector<S> = (state: S, ...args: any[]) => any;
export type ParametricKeySelector<S, P> = (
state: S,
props: P,
...args: any[]
Expand Down Expand Up @@ -45,7 +45,7 @@ type Options =
| CreateSelectorInstance;

export type OutputCachedSelector<S, R, C, D> = (
resolver: Resolver<S>,
keySelector: KeySelector<S>,
optionsOrSelectorCreator?: Options
) => OutputSelector<S, R, C, D> & {
getMatchingSelector: (state: S, ...args: any[]) => OutputSelector<S, R, C, D>;
Expand All @@ -55,7 +55,7 @@ export type OutputCachedSelector<S, R, C, D> = (
};

export type OutputParametricCachedSelector<S, P, R, C, D> = (
resolver: ParametricResolver<S, P>,
keySelector: ParametricKeySelector<S, P>,
optionsOrSelectorCreator?: Options
) => OutputParametricSelector<S, P, R, C, D> & {
getMatchingSelector: (
Expand Down
10 changes: 5 additions & 5 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const defaultCacheCreator = FlatObjectCache;
const defaultCacheKeyValidator = () => true;

function createCachedSelector(...funcs) {
return (resolver, options = {}) => {
return (keySelector, options = {}) => {
// @NOTE Versions 0.x/1.x accepted "options" as a function
if (typeof options === 'function') {
throw new Error(
Expand All @@ -30,7 +30,7 @@ function createCachedSelector(...funcs) {

// Application receives this function
const selector = function(...args) {
const cacheKey = resolver(...args);
const cacheKey = keySelector(...args);

if (isValidCacheKey(cacheKey)) {
let cacheResponse = cache.get(cacheKey);
Expand All @@ -43,20 +43,20 @@ function createCachedSelector(...funcs) {
return cacheResponse(...args);
}
console.warn(
`[re-reselect] Invalid cache key "${cacheKey}" has been returned by resolver function.`
`[re-reselect] Invalid cache key "${cacheKey}" has been returned by keySelector function.`
);
return undefined;
};

// Further selector methods
selector.getMatchingSelector = (...args) => {
const cacheKey = resolver(...args);
const cacheKey = keySelector(...args);
// @NOTE It might update cache hit count in LRU-like caches
return cache.get(cacheKey);
};

selector.removeMatchingSelector = (...args) => {
const cacheKey = resolver(...args);
const cacheKey = keySelector(...args);
cache.remove(cacheKey);
};

Expand Down

0 comments on commit bddd82e

Please sign in to comment.