0
# React Cache
1
2
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.
3
4
**⚠️ Experimental Package**: This package is explicitly unstable and not recommended for production use. The API will change between versions.
5
6
## Package Information
7
8
- **Package Name**: react-cache
9
- **Package Type**: npm
10
- **Language**: JavaScript (with Flow types)
11
- **Installation**: This is a private package within the React monorepo and not directly installable
12
- **React Version**: Requires React ^17.0.0 (peer dependency)
13
14
## Core Imports
15
16
```javascript
17
import { unstable_createResource, unstable_setGlobalCacheLimit } from "react-cache";
18
```
19
20
CommonJS:
21
22
```javascript
23
const { unstable_createResource, unstable_setGlobalCacheLimit } = require("react-cache");
24
```
25
26
## Basic Usage
27
28
```javascript
29
import React, { Suspense } from "react";
30
import { unstable_createResource } from "react-cache";
31
32
// Create a resource for fetching user data
33
const UserResource = unstable_createResource(
34
async (userId) => {
35
const response = await fetch(`/api/users/${userId}`);
36
return response.json();
37
},
38
(userId) => `user-${userId}` // Optional hash function for cache keys
39
);
40
41
function UserProfile({ userId }) {
42
// This will suspend if data is not cached, or return cached data
43
const user = UserResource.read(userId);
44
45
return (
46
<div>
47
<h1>{user.name}</h1>
48
<p>{user.email}</p>
49
</div>
50
);
51
}
52
53
function App() {
54
return (
55
<Suspense fallback={<div>Loading...</div>}>
56
<UserProfile userId={123} />
57
</Suspense>
58
);
59
}
60
```
61
62
## Architecture
63
64
React Cache is built around several key components:
65
66
- **Resource Pattern**: Resources encapsulate async data fetching with built-in caching
67
- **Suspense Integration**: Uses React's suspense mechanism by throwing promises during pending states
68
- **LRU Cache**: Internal Least Recently Used cache with configurable limits and automatic cleanup
69
- **Status Tracking**: Three-state system (Pending/Resolved/Rejected) for cache entries
70
- **Hash Functions**: Customizable key generation for cache storage
71
72
## Capabilities
73
74
### Resource Creation
75
76
Creates a cached resource that integrates with React Suspense for data fetching.
77
78
```javascript { .api }
79
/**
80
* Creates a resource that can cache async data fetching results
81
* @param fetch - Function that returns a thenable (promise-like) for data fetching
82
* @param maybeHashInput - Optional hash function for generating cache keys (defaults to identity function)
83
* @returns Resource object with read and preload methods
84
*/
85
function unstable_createResource<I, K, V>(
86
fetch: (input: I) => Thenable<V>,
87
maybeHashInput?: (input: I) => K
88
): Resource<I, V>;
89
90
interface Resource<I, V> {
91
/**
92
* Reads cached data or suspends if data is not available
93
* Throws the promise if pending, throws error if rejected, returns value if resolved
94
*/
95
read(input: I): V;
96
97
/**
98
* Preloads data into cache without returning the value
99
* Useful for prefetching data before it's needed
100
*/
101
preload(input: I): void;
102
}
103
```
104
105
**Usage Example:**
106
107
```javascript
108
// Simple resource with identity hash function
109
const SimpleResource = unstable_createResource(async (id) => {
110
return fetch(`/api/data/${id}`).then(r => r.json());
111
});
112
113
// Resource with custom hash function for complex inputs
114
const ComplexResource = unstable_createResource(
115
async ({ userId, type, filters }) => {
116
const params = new URLSearchParams({ userId, type, ...filters });
117
return fetch(`/api/complex?${params}`).then(r => r.json());
118
},
119
({ userId, type, filters }) => `${userId}-${type}-${JSON.stringify(filters)}`
120
);
121
122
// Preload data before component renders
123
ComplexResource.preload({ userId: 123, type: 'profile', filters: { active: true } });
124
```
125
126
### Global Cache Configuration
127
128
Sets the global cache limit for all resources.
129
130
```javascript { .api }
131
/**
132
* Sets the global cache limit for all resources
133
* @param limit - Maximum number of cached entries across all resources
134
*/
135
function unstable_setGlobalCacheLimit(limit: number): void;
136
```
137
138
**Usage Example:**
139
140
```javascript
141
import { unstable_setGlobalCacheLimit } from "react-cache";
142
143
// Set global cache to hold maximum 1000 entries
144
unstable_setGlobalCacheLimit(1000);
145
146
// Default limit is 500 entries
147
```
148
149
## Types
150
151
### Resource Interface
152
153
```javascript { .api }
154
/**
155
* Resource interface for cached data fetching
156
*/
157
interface Resource<I, V> {
158
read(input: I): V;
159
preload(input: I): void;
160
}
161
```
162
163
### Core Types
164
165
```javascript { .api }
166
/**
167
* Promise-like interface used by React Cache
168
*/
169
interface Thenable<T> {
170
then<U>(
171
onFulfill?: (value: T) => U | Thenable<U>,
172
onReject?: (error: any) => U | Thenable<U>
173
): Thenable<U>;
174
}
175
```
176
177
### Cache Entry States
178
179
```javascript { .api }
180
/**
181
* Internal cache entry result types (for reference)
182
*/
183
type PendingResult = {
184
status: 0;
185
value: Thenable<any>; // The suspender thenable
186
};
187
188
type ResolvedResult<V> = {
189
status: 1;
190
value: V;
191
};
192
193
type RejectedResult = {
194
status: 2;
195
value: any; // The error
196
};
197
198
type Result<V> = PendingResult | ResolvedResult<V> | RejectedResult;
199
```
200
201
## Error Handling
202
203
React Cache integrates with React's error boundaries for error handling:
204
205
```javascript
206
// Errors thrown by fetch functions will be re-thrown when read() is called
207
const ErrorProneResource = unstable_createResource(async (id) => {
208
const response = await fetch(`/api/data/${id}`);
209
if (!response.ok) {
210
throw new Error(`Failed to fetch: ${response.status}`);
211
}
212
return response.json();
213
});
214
215
function ErrorBoundary({ children }) {
216
return (
217
<React.ErrorBoundary
218
fallback={<div>Something went wrong!</div>}
219
onError={(error) => console.error('Cache error:', error)}
220
>
221
{children}
222
</React.ErrorBoundary>
223
);
224
}
225
```
226
227
## Important Constraints
228
229
- **Render Phase Only**: `read()` and `preload()` methods can only be called during React component render phase
230
- **Suspense Required**: Components using `resource.read()` must be wrapped in a `<Suspense>` boundary
231
- **Key Limitations**: Default hash function only supports primitive types (string, number, symbol, boolean, null, undefined)
232
- **React Version**: Requires React 17.0.0 or higher
233
- **Experimental Status**: API is subject to breaking changes without notice