diff --git a/src/routes/solid-router/reference/data-apis/cache.mdx b/src/routes/solid-router/reference/data-apis/cache.mdx index 5601da146..86e3ec34a 100644 --- a/src/routes/solid-router/reference/data-apis/cache.mdx +++ b/src/routes/solid-router/reference/data-apis/cache.mdx @@ -2,29 +2,35 @@ title: cache --- -Cache is used to prevent duplicate fetching and to trigger handle refetching. -It takes a function and returns the same function. +`cache` is a [higher-order function](https://en.wikipedia.org/wiki/Higher-order_function) designed to create a new function with the same signature as the function passed to it. +When this newly created function is called for the first time with a specific set of arguments, the original function is run, and its return value is stored in a cache and returned to the caller of the created function. +The next time the created function is called with the same arguments (as long as the cache is still valid), it will return the cached value instead of re-executing the original function. -```jsx -const getUser = cache((id) => { - return (await fetch(`/api/users${id}`)).json() -}, "users") // used as cache key + serialized arguments -``` + + +`cache` can be defined anywhere and then used inside your components with [`createAsync`](/solid-router/reference/data-apis/create-async). -It is expected that the arguments to the cache function are serializable. +However, using `cache` directly in [`createResource`](/reference/basic-reactivity/create-resource) will not work since the fetcher is not reactive and will not invalidate properly. -This cache accomplishes the following: + -1. Deduping on the server for the lifetime of the request. -2. Preloading the cache in the browser - this lasts 10 seconds. - When a route is preloaded on hover or when load is called when entering a route it will make sure to dedupe calls. -3. A reactive refetch mechanism based on key. - This prevents routes that are not new from retriggering on action revalidation. -4. Serve as a back/forward cache for browser navigation for up to 5 minutes. - Any user based navigation or link click bypasses it. - Upon revalidation or new fetch the cache is updated. +## Usage + +```js +const getUser = cache( + (id, options = {}) => fetch(`/api/users/${id}?summary=${options.summary || false}`).then(r => r.json()), + "usersById" +); + +getUser(123); // Causes a GET request to /api/users/123?summary=false +getUser(123); // Does not cause a GET request +getUser(123, { summary: true }); // Causes a GET request to /api/users/123?summary=true +setTimeout(() => getUser(123, { summary: true }), 999000); // Eventually causes another GET request to /api/users/123?summary=true +``` + +### With load functions -Using it with a load function: +Using it with a [load function](https://docs.solidjs.com/solid-router/reference/load-functions/load): ```js import { lazy } from "solid-js"; @@ -42,7 +48,9 @@ function loadUser({params, location}) { ; ``` -Inside your page component you: +### Inside a route's component + +Using it inside a route's component: ```jsx // pages/users/[id].js @@ -54,22 +62,56 @@ export default function User(props) { } ``` -Cached functions provide a few useful methods for getting the key that can be used in cases with invalidation: +## Cach function capabilities + +`cache` accomplishes the following: + +1. Deduping on the server for the lifetime of the request. +2. Preloading the cache in the browser - this lasts 10 seconds. + When a route is preloaded on hover or when load is called when entering a route it will make sure to dedupe calls. +3. A reactive refetch mechanism based on key. + This prevents routes that are not new from retriggering on action revalidation. +4. Serve as a back/forward cache for browser navigation for up to 5 minutes. + Any user based navigation or link click bypasses it. + Upon revalidation or new fetch the cache is updated. + +## Cache keys + +To ensure that the cache keys are consistent and unique, arguments are deterministically serialized using JSON.stringify. +Before serialization, key/value pairs in objects are sorted so that the order of properties does not affect the serialization. +For instance, both `{ name: 'Ryan', awesome: true }` and `{ awesome: true, name: 'Ryan' }` will serialize to the same string so that they produce the same cache key. + +## Return value + +The return value is a `CachedFunction`, a function that has the same signature as the function you passed to `cache`. +This cached function stores the return value using the cache key. +Under most circumstances, this temporarily prevents the passed function from running with the same arguments, even if the created function is called repeatedly. + +## Arguments + +| argument | type | description | +| -------- | ---- | ----------- | +| `fn` | `(...args: any) => any` | A function whose return value you'd like to be cached. | +| `name`* | string | Any arbitrary string that you'd like to use as the rest of the cache key. | + +*Since the internal cache is shared by all the functions using `cache`, the string should be unique for each function passed to `cache`. +If the same key is used with multiple functions, one function might return the cached result of the other. + +## Methods + +### `.key` and `.keyFor` + +Cached functions provide `.key` and `.keyFor`, are useful when retrieving the keys used in cases involving invalidation: ```ts let id = 5; - getUser.key; // returns "users" getUser.keyFor(id); // returns "users[5]" ``` +### `revalidate` + The cache can be revalidated using the `revalidate` method or the `revalidate` keys that are set on the response from the actions. -If the whole key is passed, it will invalidate all entries for the cache (ie. `users` in the example above). +If the entire key is passed, it will invalidate all entries for the cache (ie. `users` in the example above). If only a single entry needs to be invalidated, `keyFor` is provided. - - - `cache` can be defined anywhere and then used inside your components with [`createAsync`](/solid-router/reference/data-apis/create-async). - -However, using `cache` directly in [`createResource`](/reference/basic-reactivity/create-resource) will not work since the fetcher is not reactive and will not invalidate properly. - - +To revalidate everything in the cache, pass `undefined` as the key.