A React hook for accessing an async cache that persists data between renders and components. This allows you to do neat stuff like preload data before your next page or component has even started mounting.
npm install @react-hook/cachenpm i @react-hook/cache
A React hook for accessing an asynchronous key/value cache that persists data between renders and
components. This allows you to do neat stuff like preload data before your next
page or component has even started mounting.
| Section | Description |
| -------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| Quick Start | A usage example |
| createCache() | Creates an asynchronous LRU cache which can be used with the useCache() hook. Cache keys _must_ be a string type. |
| useCache() | A hook for reading and loading items from a persistent cache created by the createCache() function. |
Check out this example on CodeSandbox
``jsx harmony
import * as React from 'react'
import {createCache, useCache} from '@react-hook/cache'
// Creates a fetch cache w/ a max of 400 entries for JSON requests
const fetchCache = createCache(async (key, options) => {
const response = await fetch(key, options)
return response.json()
}, 400)
const Todo = ({id: initialId = 1}) => {
const [id, setId] = React.useState(initialId)
const [{status, value, error, cancel}, fetchTodo] = useCache(
fetchCache,
https://jsonplaceholder.typicode.com/todos/${id}
)
// Loads the todo
React.useEffect(() => {
// We only want to load our todo if we don't already have it in this
// case. BUT because the value always persists between 'success' states
// you could always be revalidating here regardless and change the if ... else
// blocks to check 'value' instead of 'status' to determine if the todo
// should display
if (status === 'idle') {
fetchTodo()
}
}, [fetchTodo, id, status])
if (status === 'loading') {
return (
return (
)
}
// Proceeds to the next todo
onClick={() => setId(nextId)}
>
Next todo
API
$3
Creates an asynchronous LRU cache which can be used with the
useCache() hook.
Cache keys _must_ be a string type.`ts
export const createCache = (
resolve: (key: string, ...args: any[]) => Promise,
lruSize = Infinity
): Cache
`#### Arguments
| Argument | Type | Default | Required? | Description |
| -------- | ------------------------------------------------- | ---------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| resolve |
(key: string, ...args: any[]) => Promise | | Yes | A callback that returns the value for a key. ...args in the callback signature are provided by the user when they call cache.load(). |
| lruSize | number | Infinity | No | The max number of key/value pairs to cache at a given time. When the number of cache items exceeds this number, the item least recently accessed will be purged from the cache. |#### Returns Cache
$3
A hook for reading and loading items from a persistent cache created by the
createCache() function.`ts
export const useCache = <
Value = any,
ErrorType = Error,
Args extends any[] = any[]
>(
cache: Cache,
key: string,
...args: Args
): [
UseCacheState,
() => Promise>
]
`#### Arguments
| Argument | Type | Required? | Description |
| -------- | ----------------- | --------- | ----------------------------------------------------------- |
| cache |
Cache | Yes | A cache created by the createCache() function |
| key | string | Yes | The cache key to read or load from the cache |
| ...args | [] | No | Arguments passed to the cache.load(key, ...args) function |#### Returns [UseCacheState,
() => Promise]The second element in the array will load the value associated with the provided
key and
reload it in the case that a value already exists.Types
$3
`ts
export type Cache<
Value = any,
ErrorType = Error,
Args extends any[] = any[]
> = {
/**
* Loads a key and provides its other ...args to the resolver
*/
load: (key: string, ...args: Args) => Promise>
/**
* Reads a key in the LRU cache and returns its value if there is one, otherwise
* returns undefined
*/
read: (key: string) => CacheState | undefined
/**
* Cancels any pending promises for key
*/
cancel: (key: string) => void
/**
* Returns a {[key: string]: CacheState} object. This can be used
* for persisting the state rendered on a server to the client.
*/
readAll: () => CacheExport>
/**
* Writes a {[key: string]: CacheState} to the LRU cache. This can be used
* for persisting the state rendered on a server to the client.
*/
write: (input: CacheExport) => void
/**
* Subscribes to changes to key. That is, callback will be invoked
* any time the state assigned to key changed.
*/
subscribe: (
key: string,
callback: CacheSubscribeCallback>
) => void
/**
* Unsubscribes to changes to key
*/
unsubscribe: (
key: string,
callback: CacheSubscribeCallback>
) => void
}
`$3
`ts
export type CacheState =
| {
id: number
/**
* The cache is currently loading a value for this key
*/
status: 'loading'
/**
* This will be the previous value if there is one, otherwise undefined
*/
value: Value | undefined
/**
* Loading states will never have an error message
*/
error: undefined
}
| {
id: number
/**
* The cache has successfully loaded a value for the key
*/
status: 'success'
/**
* This is the value loaded by the cache
*/
value: Value
/**
* Success states will never have an error message
*/
error: undefined
}
| {
id: number
/**
* The cache encountered an error when loading a value for the key
*/
status: 'error'
/**
* This is the previous value if there is one, otherwise undefined
*/
value: Value | undefined
/**
* This is the error object that was caught during execution
*/
error: ErrorType
}
| {
id: number
/**
* The request for this key was cancelled before it was completed
*/
status: 'cancelled'
/**
* This is the previous value if there isone, otherwise undefined
*/
value: Value | undefined
/**
* Cancelled states never have an error message
*/
error: undefined
}
`$3
`ts
export type UseCacheState =
| {
/**
* The key does not exist in the cache and the cache has not started
* loading this key
*/
status: 'idle'
/**
* When idle we have no current or previous value available
*/
value: undefined
/**
* No errors will be reported here
*/
error: undefined
/**
* Cancelling will have no effect when idle
*/
cancel: () => void
}
| {
/**
* The next value for the key is currently loading in the cache
*/
status: 'loading'
/**
* The previous value for this key will persist during the loading phase.
*/
value: Value | undefined
/**
* No errors will be reported
*/
error: undefined
/**
* Cancelling will prevent the value returned in this request from being
* added to state
*/
cancel: () => void
}
| {
/**
* The key does not exist in the cache and the cache has not started
* loading this key
*/
status: 'cancelled'
/**
* The previous value for this key will persist during the loading phase.
*/
value: Value | undefined
/**
* No errors will be reported
*/
error: undefined
/**
* Cancelling has no effect here
*/
cancel: () => void
}
| {
/**
* We have successfully received a value for the key
*/
status: 'success'
/**
* The value returned by the successful request
*/
value: Value
/**
* No errors will be reported here
*/
error: undefined
/**
* Cancelling will have no effect here
*/
cancel: () => void
}
| {
/**
* The promise in the cache encountered an error
*/
status: 'error'
/**
* The last successful value received by the cache will persist here
*/
value: Value | undefined
/**
* This is the error object encountered by the request
*/
error: ErrorType
/**
* Cancelling will have no effect here
*/
cancel: () => void
}
``MIT