Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions client/lib/create-selector/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ const sitePosts = getSitePosts( state, siteId );

This result would only be calculated once, so long as `state.posts` remains the same.

`createSelectorPerKey` accept the same parameters as `createSelector`.
The difference is how it invalidate the cache and as the name suggest it is per-key and not per-selector.

For example, the stats module have state section that stores all the different stats types keyed by a query. This function allows the dependent data function to return a very specific sub-tree of the state and if that sub-tree changes only the current cache key (3rd parameter) will be invalidated. In the stats case when authors stats changes only it will be invalidated while posts stats will still be served from the cache.

Please note the effect might be higher memory usage because invalid cache keys will not be reevaluated until they are requested, which might never happen.

## FAQ

### What is a memoized selector?
Expand Down
26 changes: 26 additions & 0 deletions client/lib/create-selector/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
import memoize from 'lodash/memoize';
import shallowEqual from 'react-pure-render/shallowEqual';
import { isEqual } from 'lodash';

/**
* Constants
Expand Down Expand Up @@ -105,3 +106,28 @@ export default function createSelector( selector, getDependants = DEFAULT_GET_DE
}, { memoizedSelector } );
}

export function createSelectorPerKey( selector, getDependants = DEFAULT_GET_DEPENDANTS, getCacheKey = DEFAULT_GET_CACHE_KEY ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we possibly add some test coverage for this new function?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You right, I've pushed commit with tests for the new method. I'm using the existing test suite of createSelector and added test specific for the new method.

const memoizedSelector = memoize( selector, getCacheKey );
const lastDependantsByKey = {};

if ( Array.isArray( getDependants ) ) {
getDependants = makeSelectorFromArray( getDependants );
}

return Object.assign( function( state, ...args ) {
let currentDependants = getDependants( state, ...args );
if ( ! Array.isArray( currentDependants ) ) {
currentDependants = [ currentDependants ];
}

const cacheKey = getCacheKey( state, ...args );
const lastDependants = lastDependantsByKey[ cacheKey ];
if ( lastDependants && ! shallowEqual( currentDependants, lastDependants ) ) {
memoizedSelector.cache.delete( cacheKey );
}

lastDependantsByKey[ cacheKey ] = currentDependants;

return memoizedSelector( state, ...args );
}, { memoizedSelector } );
}
Loading