@vlsergey/react-cache-context
v0.7.0
Published
React Context for caching values by key, optionally with batched values supplier
Downloads
19
Maintainers
Readme
@vlsergey/react-cache-context
React Context for caching values by key.
Main features:
- [x] Key-value cache with simple
useCacheValue()
hook - [x] Supports multiple caches, each uses it's own React context. Updating single cache will not result in whole-application rerender.
- [x] Can be integrated with LRU / TTL map implementations with
mapSupplier
property.
Installation:
npm install --save @vlsergey/react-cache-context
or
npm install --save-dev @vlsergey/react-cache-context
Usage
// in application root
import {CachesStore, RegisterCache} from "@vlsergey/react-cache-context";
/* ... */
// include CachesStore inside any authorization providers/wrappers if any present,
// but outside of routing providers
return <CachesStore>
<RegisterCache
cacheId="groupsCache"
getter={ async ( groupId ) => (await new Api().groups.findById( groupId )).data }>
<RegisterCache
cacheId="studentsCache"
getter={ async ( studentId ) => (await new Api().students.findById( studentId )).data }>
{ /* ... */ }
</RegisterCache>
</RegisterCache>
</CachesStore>
// in some (function) component
import {useCacheValue} from "@vlsergey/react-cache-context";
const StudentName = ( studentId ) => {
const student = useCacheValue( 'studentsCache', studentId );
return (student || {}).name || studentId;
}
API
<CachesStore>
Root element, holds map of all caches contexts. All <RegisterCache>
elements must be inside of <CachesStore>
.
It is advised to include <CachesStore>
after/inside or any authentication wrappers if any present, thus invalidating all caches if user changed due to relogin.
| Property | Data type | Default value | Description |
| ----------------------- | ---------------------------------------------- | ------------- | ----------- |
| caches
| Record<string, CacheSpec<unknown, unknown>>
| undefined
| Can be used instead of multiple <RegisterCache>
to register caches. CacheSpec
can be either simple item getter function ((key: K) => Promise<V>
) or object with getter
, missingValue
and mapSupplier
properties from <RegisterCache>
|
<RegisterCache>
Registers and holds values (errors, loading state) of single cache.
Any number or <RegisterCache>
with different cacheId
can be used.
Multiple elements with same cacheId
can be used, but only one of them (nearest parent to current functional component) will actually provide values.
Be careful with autogenerated cacheId
, because map entries from cacheId
to react context type are not garbage collected.
| Property | Data type | Default value | Description |
| ----------------------- | ---------------------------------------------- | ------------- | ----------- |
| cacheId
| string | required | Identifies cache context. Will be used by client hooks later to provide access particular context holded (provided) by current <RegisterCache>
element. |
| getter
| (key: K) => Promise | required | Explains to library how to obtain element. May throw an error. Promise may return null
or undefined
and those will be remembered as results. |
| mapSupplier
| (cacheId: string) => CacheMap<K, T> | () => new Map()
| Can be used to provide custom (LRU, TTL) map implementation to store errors/results |
| missingValue
| V
| undefined
| What should hooks return if value not available yet. |
useCache( cacheId: string ) : CacheContext<K, V>
Provide access to cache context with specified cacheId
. Hook should be called inside component inside corresponding <RegisterCache>
element (otherwise all calls to it's methods will result in error).
CacheContext<K, V>
provides man methods to get or invalidate information from single cache:
interface CacheContext<K extends Key, V> {
clear: () => unknown;
delete: (key: K) => unknown;
get: (key: K) => V;
getPromise: (key: K) => Promise<V>;
}
useCacheValue<K, V>( cacheId: string, key: K ) : V
Returns currently stored value from cache or throws error if last call of getter
with provided key resulted an error. If no value present (and loading is not in progress yet) will generate async call to getter
to obtain value.
If no value and no error present in cache immediately returns missingValue
property of <RegisterCache>
, or undefined
if such property were not set.
Current implementation will retry to obtain value if last getter
returns an error.
useCachePromise<K, V>( cacheId: string, key: K ) : V
Returns currently stored value from cache (as Promise.resolve(…)
). If no value present new promise is obtained from getter
and returned as result. This method ignores stored errors (i.e. always repeat failed queries), but only one query is executed at the same time for any particular key.
Use as LRU (last recently used) or TTL cache
With mapSupplier
property of RegisterCache
component one can use LRU or TTL map implementations as internal cache store. Note, that internally two maps are used for each cache: map of values (CacheMap<K, V>
) and maps of errors (CacheMap<K, unknown>
).
Provided map must conform to following interface (partial interface of JavaScript Map
):
interface CacheMap<K extends Key, V> {
clear: () => unknown;
delete: (key: K) => unknown;
has: (key: K) => boolean;
get: (key: K) => V;
set: (key: K, value: V) => unknown;
}