or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-react-cache

A basic cache for React applications designed for experimental features with suspense-based data fetching

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/react-cache@2.0.x

To install, run

npx @tessl/cli install tessl/npm-react-cache@2.0.0

index.mddocs/

React Cache

React Cache is a basic cache for React applications that provides suspense-based data fetching capabilities. It serves as a reference implementation for more advanced caching solutions and is designed to work alongside experimental React features.

⚠️ Experimental Package: This package is explicitly unstable and not recommended for production use. The API will change between versions.

Package Information

  • Package Name: react-cache
  • Package Type: npm
  • Language: JavaScript (with Flow types)
  • Installation: This is a private package within the React monorepo and not directly installable
  • React Version: Requires React ^17.0.0 (peer dependency)

Core Imports

import { unstable_createResource, unstable_setGlobalCacheLimit } from "react-cache";

CommonJS:

const { unstable_createResource, unstable_setGlobalCacheLimit } = require("react-cache");

Basic Usage

import React, { Suspense } from "react";
import { unstable_createResource } from "react-cache";

// Create a resource for fetching user data
const UserResource = unstable_createResource(
  async (userId) => {
    const response = await fetch(`/api/users/${userId}`);
    return response.json();
  },
  (userId) => `user-${userId}` // Optional hash function for cache keys
);

function UserProfile({ userId }) {
  // This will suspend if data is not cached, or return cached data
  const user = UserResource.read(userId);
  
  return (
    <div>
      <h1>{user.name}</h1>
      <p>{user.email}</p>
    </div>
  );
}

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <UserProfile userId={123} />
    </Suspense>
  );
}

Architecture

React Cache is built around several key components:

  • Resource Pattern: Resources encapsulate async data fetching with built-in caching
  • Suspense Integration: Uses React's suspense mechanism by throwing promises during pending states
  • LRU Cache: Internal Least Recently Used cache with configurable limits and automatic cleanup
  • Status Tracking: Three-state system (Pending/Resolved/Rejected) for cache entries
  • Hash Functions: Customizable key generation for cache storage

Capabilities

Resource Creation

Creates a cached resource that integrates with React Suspense for data fetching.

/**
 * Creates a resource that can cache async data fetching results
 * @param fetch - Function that returns a thenable (promise-like) for data fetching
 * @param maybeHashInput - Optional hash function for generating cache keys (defaults to identity function)
 * @returns Resource object with read and preload methods
 */
function unstable_createResource<I, K, V>(
  fetch: (input: I) => Thenable<V>,
  maybeHashInput?: (input: I) => K
): Resource<I, V>;

interface Resource<I, V> {
  /** 
   * Reads cached data or suspends if data is not available
   * Throws the promise if pending, throws error if rejected, returns value if resolved
   */
  read(input: I): V;
  
  /** 
   * Preloads data into cache without returning the value
   * Useful for prefetching data before it's needed
   */
  preload(input: I): void;
}

Usage Example:

// Simple resource with identity hash function
const SimpleResource = unstable_createResource(async (id) => {
  return fetch(`/api/data/${id}`).then(r => r.json());
});

// Resource with custom hash function for complex inputs
const ComplexResource = unstable_createResource(
  async ({ userId, type, filters }) => {
    const params = new URLSearchParams({ userId, type, ...filters });
    return fetch(`/api/complex?${params}`).then(r => r.json());
  },
  ({ userId, type, filters }) => `${userId}-${type}-${JSON.stringify(filters)}`
);

// Preload data before component renders
ComplexResource.preload({ userId: 123, type: 'profile', filters: { active: true } });

Global Cache Configuration

Sets the global cache limit for all resources.

/**
 * Sets the global cache limit for all resources
 * @param limit - Maximum number of cached entries across all resources
 */
function unstable_setGlobalCacheLimit(limit: number): void;

Usage Example:

import { unstable_setGlobalCacheLimit } from "react-cache";

// Set global cache to hold maximum 1000 entries
unstable_setGlobalCacheLimit(1000);

// Default limit is 500 entries

Types

Resource Interface

/**
 * Resource interface for cached data fetching
 */
interface Resource<I, V> {
  read(input: I): V;
  preload(input: I): void;
}

Core Types

/**
 * Promise-like interface used by React Cache
 */
interface Thenable<T> {
  then<U>(
    onFulfill?: (value: T) => U | Thenable<U>,
    onReject?: (error: any) => U | Thenable<U>
  ): Thenable<U>;
}

Cache Entry States

/**
 * Internal cache entry result types (for reference)
 */
type PendingResult = {
  status: 0;
  value: Thenable<any>; // The suspender thenable
};

type ResolvedResult<V> = {
  status: 1;
  value: V;
};

type RejectedResult = {
  status: 2;
  value: any; // The error
};

type Result<V> = PendingResult | ResolvedResult<V> | RejectedResult;

Error Handling

React Cache integrates with React's error boundaries for error handling:

// Errors thrown by fetch functions will be re-thrown when read() is called
const ErrorProneResource = unstable_createResource(async (id) => {
  const response = await fetch(`/api/data/${id}`);
  if (!response.ok) {
    throw new Error(`Failed to fetch: ${response.status}`);
  }
  return response.json();
});

function ErrorBoundary({ children }) {
  return (
    <React.ErrorBoundary
      fallback={<div>Something went wrong!</div>}
      onError={(error) => console.error('Cache error:', error)}
    >
      {children}
    </React.ErrorBoundary>
  );
}

Important Constraints

  • Render Phase Only: read() and preload() methods can only be called during React component render phase
  • Suspense Required: Components using resource.read() must be wrapped in a <Suspense> boundary
  • Key Limitations: Default hash function only supports primitive types (string, number, symbol, boolean, null, undefined)
  • React Version: Requires React 17.0.0 or higher
  • Experimental Status: API is subject to breaking changes without notice