1.1.1 • Published 4 years ago
@react-hook/cache v1.1.1
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.
Contents
| 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 astringtype. | 
| useCache() | A hook for reading and loading items from a persistent cache created by the createCache()function. | 
Quick Start
Check out this example on CodeSandbox
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 (
      <div>
        Loading {id}...
        <button onClick={cancel}>Cancel</button>
      </div>
    )
  } else if (status === 'error') {
    return (
      <div>
        Error: {error.mesage} <button onClick={fetchTodo}>Try again</button>
      </div>
    )
  } else if (status === 'cancelled') {
    return (
      <div>
        Cancelled <button onClick={fetchTodo}>Load again</button>
      </div>
    )
  } else if (status === 'success') {
    const nextId = id + 1
    return (
      <div>
        <h1>{value.title}</h1>
        <button
          // Preloads the next todo on mouse enter
          onMouseEnter={() =>
            fetchCache.load(
              `https://jsonplaceholder.typicode.com/todos/${nextId}`
            )
          }
          // Proceeds to the next todo
          onClick={() => setId(nextId)}
        >
          Next todo
        </button>
      </div>
    )
  }
  // 'idle' status
  return null
}API
createCache(resolver, lruSize)
Creates an asynchronous LRU cache which can be used with the useCache() hook.
Cache keys must be a string type.
export const createCache = <Value = any, ErrorType = Error>(
  resolve: (key: string, ...args: any[]) => Promise<Value>,
  lruSize = Infinity
): Cache<Value, ErrorType>Arguments
| Argument | Type | Default | Required? | Description | 
|---|---|---|---|---|
| resolve | (key: string, ...args: any[]) => Promise<Value> | Yes | A callback that returns the value for a key....argsin the callback signature are provided by the user when they callcache.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
useCache(cache, key, ...args)
A hook for reading and loading items from a persistent cache created by the
createCache() function.
export const useCache = <
  Value = any,
  ErrorType = Error,
  Args extends any[] = any[]
>(
  cache: Cache<Value, ErrorType, Args>,
  key: string,
  ...args: Args
): [
  UseCacheState<Value, ErrorType>,
  () => Promise<CacheState<Value, ErrorType>>
]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<CacheState<Value, ErrorType>>]
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
Cache
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<CacheState<Value, ErrorType>>
  /**
   * Reads a `key` in the LRU cache and returns its value if there is one, otherwise
   * returns undefined
   */
  read: (key: string) => CacheState<Value, ErrorType> | 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<CacheState<Value, ErrorType>>
  /**
   * 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<Value, ErrorType>) => 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<CacheState<Value, ErrorType>>
  ) => void
  /**
   * Unsubscribes to changes to `key`
   */
  unsubscribe: (
    key: string,
    callback: CacheSubscribeCallback<CacheState<Value, ErrorType>>
  ) => void
}CacheState
export type CacheState<Value = any, ErrorType = Error> =
  | {
      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
    }UseCacheState
export type UseCacheState<Value = any, ErrorType = Error> =
  | {
      /**
       * 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
    }LICENSE
MIT
1.1.1
4 years ago
1.1.0
5 years ago
1.0.0
5 years ago
0.1.0-alpha.7
6 years ago
0.1.0-alpha.6
6 years ago
0.1.0-alpha.5
6 years ago
0.1.0-alpha.4
6 years ago
0.1.0-alpha.3
6 years ago
0.1.0-alpha.2
6 years ago
0.1.0-alpha.1
6 years ago
0.1.0-alpha.0
6 years ago
0.1.0-alpha
6 years ago