Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Enhance Reselect selectors with deeper memoization and cache management.

License

NotificationsYou must be signed in to change notification settings

toomuchdesign/re-reselect

Repository files navigation

Build statusNpm versionNpm downloadsTest coverage report

Fromv5,reselect provides the ability to natively implement custom memoization/caching solutions viacreateSelector options. Most of the featuresre-reselect used to enable should be now natively available inreselect.re-reselect will try to supportreselect v5+ for backward compatibility reasons.

re-reselect is a lightweight wrapper aroundReselect meant to enhance selectors withdeeper memoization andcache management.

Switching between different arguments using standardreselect selectors causescache invalidation since defaultreselect cache has alimit of one.

re-reselectforwards different calls to differentreselectselectors stored in cache, so that computed/memoized values are retained.

re-reselectselectors work as normalreselectselectors but they are able to determine whencreating a new selector or querying a cached one on the fly, depending on the supplied arguments.

Reselect and re-reselect

Useful to:

import{createCachedSelector}from're-reselect';// Normal reselect routine: declare "inputSelectors" and "resultFunc"constgetUsers=state=>state.users;constgetLibraryId=(state,libraryName)=>state.libraries[libraryName].id;constgetUsersByLibrary=createCachedSelector(// inputSelectorsgetUsers,getLibraryId,// resultFunc(users,libraryId)=>expensiveComputation(users,libraryId),)(// re-reselect keySelector (receives selectors' arguments)// Use "libraryName" as cacheKey(_state_,libraryName)=>libraryName);// Cached selectors behave like normal selectors:// 2 reselect selectors are created, called and cachedconstreactUsers=getUsersByLibrary(state,'react');constvueUsers=getUsersByLibrary(state,'vue');// This 3rd call hits the cacheconstreactUsersAgain=getUsersByLibrary(state,'react');// reactUsers === reactUsersAgain// "expensiveComputation" called twice in total

Table of contents

Installation

npm install reselectnpm install re-reselect

Why? + example

Let's saygetData is areselect selector.

getData(state,itemId,'dataA');getData(state,itemId,'dataB');getData(state,itemId,'dataA');

The3rd argument invalidatesreselect cache on each call, forcinggetData to re-evaluate and return a new value.

re-reselect solution

re-reselect selectors keep acache ofreselect selectors stored bycacheKey.

cacheKey is the return value of thekeySelector function. It's by default astring ornumber but it can be anything depending on the chosen cache strategy (seecache objects docs).

keySelector is a custom function which:

  • takes the same arguments as the selector itself (in the example:state,itemId,dataType)
  • returns acacheKey

Aunique persistingreselect selector instance stored in cache is used to compute data for a givencacheKey (1:1).

Back to the example, we might setupre-reselect to retrieve data byquerying one of the cached selectors using the 3rd argument ascacheKey, allowing cache invalidation only whenstate oritemId change (but notdataType):

constgetData=createCachedSelector(state=>state,(state,itemId)=>itemId,(state,itemId,dataType)=>dataType,(state,itemId,dataType)=>expensiveComputation(state,itemId,dataType))((state,itemId,dataType)=>dataType// Use dataType as cacheKey);

Replacing a selector with a cached selector is invisible to the consuming application since the API is the same.

When a cached selector is called, the following happens behind the scenes:

  1. Evaluate thecacheKey for the current call by executingkeySelector
  2. Retrieve from cache thereselect selector stored under the givencacheKey
  3. Return found selector or create a new one if no selector was found
  4. Call returned selector with provided arguments

Other viable solutions

1- Declare a different selector for each different call

Easy, but doesn't scale. See"join similar selectors" example.

2- Declare amakeGetPieceOfData selector factory as explained in Reselect docs

The solution suggested inReselect docs is fine, but it has a few downsides:

  • Bloats your code by exposing bothget selectors andmakeGet selector factories
  • Needs to import/call the selector factory instead of directly using the selector
  • Two different instances, given the same arguments, will individually store and recompute the same result (readthis)

3- Wrap yourmakeGetPieceOfData selector factory into a memoizer function and call the returning memoized selector

This is whatre-reselect actually does. 😀

Examples

FAQ

How do I wrap my existing selector with re-reselect?

Given yourreselect selectors:

import{createSelector}from'reselect';exportconstgetMyData=createSelector(selectorA,selectorB,selectorC,(A,B,C)=>doSomethingWith(A,B,C),);

...addkeySelector in the second function call:

import{createCachedSelector}from're-reselect';exportconstgetMyData=createCachedSelector(selectorA,selectorB,selectorC,(A,B,C)=>doSomethingWith(A,B,C),)((state,arg1,arg2)=>arg2,// Use arg2 as cacheKey);

Voilà,getMyData is ready for use!

constmyData=getMyData(state,'foo','bar');
How do I use multiple inputs to set the cacheKey?

A few good examples anda bonus:

// Basic usage: use a single argument as cacheKeycreateCachedSelector(// ...)((state,arg1,arg2,arg3)=>arg3)// Use multiple arguments and chain them into a stringcreateCachedSelector(// ...)((state,arg1,arg2,arg3)=>`${arg1}:${arg3}`)// Extract properties from an objectcreateCachedSelector(// ...)((state,props)=>`${props.a}:${props.b}`)
How do I limit the cache size?

Use acacheObject which provides that feature by supplying acacheObject option.

You can also writeyour own cache strategy!

How to share a selector across multiple components while passing in props and retaining memoization?

This example shows howre-reselect would solve the scenario described inreselect docs.

How do I test a re-reselect selector?

Like a normal reselect selector!

re-reselect selectors expose the samereselect testing methods:

  • dependencies
  • resultFunc
  • recomputations
  • resetRecomputations

Read more about testing selectors onreselect docs.

Testingreselect selectors stored in the cache

Eachre-reselect selector exposes agetMatchingSelector method which returns theunderlying matching selector instance for the given arguments,instead of the result.

getMatchingSelector expects the same arguments as a normal selector callBUT returns the instance of the cached selector itself.

Once you get a selector instance you can callits public methods.

import{createCachedSelector}from're-reselect';exportconstgetMyData=createCachedSelector(selectorA,selectorB,(A,B)=>doSomethingWith(A,B))((state,arg1)=>arg1// cacheKey);// Call your selectorconstmyFooData=getMyData(state,'foo');constmyBarData=getMyData(state,'bar');// Call getMatchingSelector method to retrieve underlying reselect selectors// which generated "myFooData" and "myBarData" resultsconstmyFooDataSelector=getMyData.getMatchingSelector(state,'foo');constmyBarDataSelector=getMyData.getMatchingSelector(state,'bar');// Call reselect's selectors methodsmyFooDataSelector.recomputations();myFooDataSelector.resetRecomputations();

API

createCachedSelector

import{createCachedSelector}from're-reselect';createCachedSelector(// ...reselect's `createSelector` arguments)(keySelector|{ options})

Takes the same arguments as reselect'screateSelector and returns a new function which accepts akeySelector or anoptions object.

Returns aselector instance.

createStructuredCachedSelector

import{createStructuredCachedSelector}from're-reselect';createStructuredCachedSelector(// ...reselect's `createStructuredSelector` arguments)(keySelector|{ options})

Takes the same arguments as reselect'screateStructuredSelector and returns a new function which accepts akeySelector or anoptions object.

Returns aselector instance.

keySelector

A custom function receiving the same arguments as your selectors (andinputSelectors) andreturning acacheKey.

cacheKey isby default astring ornumber but can be anything depending on the chosen cache strategy (seecacheObject option).

ThekeySelector idea comes fromLodash's .memoize resolver.

options

keySelector

Type:function
Default:undefined

ThekeySelector used by the cached selector.

cacheObject

Type:object
Default:FlatObjectCache

An optional customcache strategy object to handle the caching behaviour. Read more aboutre-reselect's custom cache here.

keySelectorCreator

Type:function
Default:undefined

An optional function with the following signature returning thekeySelector used by the cached selector.

typekeySelectorCreator=(selectorInputs:{inputSelectors:InputSelector[];resultFunc:ResultFunc;keySelector:KeySelector;})=>KeySelector;

This allows the ability to dynamicallygeneratekeySelectors on runtime based on providedinputSelectors/resultFunc supportingkey selectors composition. It overrides any providedkeySelector.

Seeprogrammatic keySelector composition example.

selectorCreator

Type:function
Default:reselect'screateSelector

An optional function describing acustom version of createSelector.

re-reselect selector instance

createCachedSelector andcreateStructuredCachedSelector return aselector instance which extends the API of astandard reselect selector.

The followings are advanced methods and you won't need them for basic usage!

selector.getMatchingSelector(selectorArguments)

Retrieve the selector responding to the given arguments.

selector.removeMatchingSelector(selectorArguments)

Remove from the cache the selector responding to the given arguments.

selector.cache

Get the cacheObject instance being used by the selector (for advanced caching operations likethis).

selector.clearCache()

Clear wholeselector cache.

selector.dependencies

Get an array containing the providedinputSelectors. Refer to relevant discussion onReselect repo.

selector.resultFunc

GetresultFunc for easilytesting composed selectors.

selector.recomputations()

Return the number of times the selector's result function has been recomputed.

selector.resetRecomputations()

Resetrecomputations count.

selector.keySelector

GetkeySelector for utility compositions or testing.

About re-reselect

Todo's

  • Improve tests readability
  • Port to native TS based on reselect v5 approach
  • Find out whetherre-reselect should be deprecated in favour ofreselect memoization/cache options

Contributors

Thanks to you all (emoji key):

Andrea Carraro
Andrea Carraro

💻📖🚇⚠️👀
Stepan Burguchev
Stepan Burguchev

💻🤔💬👀⚠️
Sergei Grishchenko
Sergei Grishchenko

💻🤔⚠️🔧
Mateusz Burzyński
Mateusz Burzyński

💻🚇
Mitch Robb
Mitch Robb

💻⚠️
Stephane Rufer
Stephane Rufer

💻⚠️
Tracy Mullen
Tracy Mullen

💻⚠️
Sushain Cherivirala
Sushain Cherivirala

💻
Steve Mao
Steve Mao

📖
Gaurav Lahoti
Gaurav Lahoti

🐛
Lon
Lon

🐛
bratushka
bratushka

💻
Anders D. Johnson
Anders D. Johnson

📖
Július Retzer
Július Retzer

📖
Maarten Schumacher
Maarten Schumacher

🤔
Alexander Jarvis
Alexander Jarvis

🤔
Gregg B
Gregg B

💡
Ian Obermiller
Ian Obermiller

👀
Kanitkorn Sujautra
Kanitkorn Sujautra

📖
Brian Kraus
Brian Kraus

📖
el-dav
el-dav

🐛
Augustin Riedinger
Augustin Riedinger

🤔
RichardForrester
RichardForrester

🤔
Alfonso Millan
Alfonso Millan

📖
parkerault
parkerault

🐛
johannes
johannes

🐛
Alex de la Mare
Alex de la Mare

🐛💻
Alex Khizhnyi
Alex Khizhnyi

💻

About

Enhance Reselect selectors with deeper memoization and cache management.

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Contributors19


[8]ページ先頭

©2009-2025 Movatter.jp