[]previous and next page

Caching and de-duplication

Caching and de-duplication in the Data fetching guide.

For agentsUpdated

Be clear about what is and is not cached:

  • There is no shared client cache for resources. Two components that each call useResource with the same fetcher make two requests. Share one resource instead: create it in a parent (or in a context provider) and pass it down. A resource is a plain accessor, so passing props.user or putting it in context shares the request, the state and every refetch.
  • Router loaders do have a cache keyed by route id, params and loader deps, with staleTime, preloading, shared in-flight loads and invalidate. See Caching and invalidation.
  • On the server, the renderer provides a per-render resource cache keyed by the resource key, which is how values travel from the server to hydrate without a second request. See SSR, hydration and streaming. Give a resource a key option for that; it is unrelated to client-side caching.
src/shared.tsxtsx
import { type Resource, useResource } from "@shadow-js/core";

export const calls = { fetches: 0 };

function load(): Promise<string> {
  calls.fetches += 1;
  return Promise.resolve("Ada");
}

function Greeting() {
  const user = useResource(load);
  return <span>{user.latest}</span>;
}

function GreetingFromParent(props: { user: Resource<string> }) {
  return <span>{props.user.latest}</span>;
}

export function Separate() {
  return (
    <p>
      <Greeting />
      <Greeting />
    </p>
  );
}

export function Shared() {
  const user = useResource(load);
  return (
    <p>
      <GreetingFromParent user={user} />
      <GreetingFromParent user={user} />
    </p>
  );
}