7
7
![ npm] ( https://img.shields.io/npm/dm/remix-client-cache?style=plastic )
8
8
![ GitHub top language] ( https://img.shields.io/github/languages/top/Code-Forge-Net/remix-client-cache?style=plastic )
9
9
10
- <img style =" display : block ; margin : 0 auto ;" src =" ./assets/remix-cache.png " height =" 300px " align =" middle " />
10
+ <img style =" display : block ; margin : 0 auto ;" src =" ./assets/remix-cache.png " height =" 300px " align =" middle " />
11
11
12
- # Important information
13
-
14
- This library is now a part of the React Router ecosystem and runs on top of React Router. It should be compatible with remix.run but if you're having issues version
15
- 1.1.0 is the last version that will work with remix.run.
16
12
17
-
18
- remix-client-cache is a powerful and lightweight library made for Remix.run to cache your server loader data on the client using clientLoaders.
13
+ remix-client-cache is a powerful and lightweight library made for react-router v7 framework mode to cache your server loader data on the client using clientLoaders.
19
14
20
15
By default it uses the stale while revalidate strategy and hot swaps your stale info once loaded from the server. It also allows you to invalidate the cache for a specific key or multiple keys.
21
16
@@ -25,40 +20,41 @@ It comes with a default adapter that uses in memory storage to cache your data.
25
20
26
21
First party support for localStorage, sessionStorage and localforage packages. You can just provide them as the argument to ` configureGlobalCache ` .
27
22
23
+ # Important information
24
+
25
+ This library is now a part of the React Router ecosystem and runs on top of React Router. It should be compatible with remix.run but if you're having issues version
26
+ 1.1.0 is the last version that will work with remix.run.
27
+
28
28
## Install
29
29
30
- npm install remix-client-cache
30
+ ``` bash
31
+ npm install remix-client-cache
32
+ ```
31
33
32
34
## Basic usage
33
35
34
36
Here is an example usage of remix-client-cache with the default in memory adapter.
35
37
36
- ``` tsx
37
- import { json , type LoaderFunctionArgs } from " @remix-run/node " ;
38
- import { ClientLoaderFunctionArgs } from " @ remix-run/react " ;
38
+ ``` tsx
39
+ import type { Route } from " ./+types/_index " ;
40
+ import { createClientLoaderCache , CacheRoute } from " remix-client-cache " ;
39
41
40
- import { cacheClientLoader , useCachedLoaderData } from " remix-client-cache" ;
41
-
42
- export const loader = async ({ params }: LoaderFunctionArgs ) => {
42
+ // Some slow server loader
43
+ export const loader = async ({ params }: Route .LoaderArgs ) => {
43
44
const response = await fetch (
44
45
` https://jsonplaceholder.typicode.com/users/${params .user } `
45
46
);
46
47
const user = await response .json ();
47
48
await new Promise ((resolve ) => setTimeout (resolve , 1000 ));
48
- return json ( { user: { ... user , description: Math .random () } }) ;
49
+ return { user: { ... user , description: Math .random () } };
49
50
};
50
51
51
-
52
52
// Caches the loader data on the client
53
- export const clientLoader = (args : ClientLoaderFunctionArgs ) => cacheClientLoader (args );
54
-
55
- // make sure you turn this flag on
56
- clientLoader .hydrate = true ;
53
+ export const clientLoader = createClientLoaderCache <Route .ClientLoaderArgs >();
57
54
58
- export default function Index() {
59
55
// The data is automatically cached for you and hot swapped when refetched
60
- const { user } = useCachedLoaderData < typeof loader >();
61
-
56
+ export default CacheRoute ( function Index({ loaderData } : Route . LoaderData ) {
57
+ const { user } = loaderData ;
62
58
return (
63
59
<div >
64
60
{ user .name } <hr /> { user .email }
@@ -69,7 +65,7 @@ export default function Index() {
69
65
{ user .description }
70
66
</div >
71
67
);
72
- }
68
+ })
73
69
74
70
```
75
71
@@ -86,7 +82,7 @@ The `cacheLoaderData` will use the default memory cache adapter that comes with
86
82
87
83
``` ts
88
84
// Inside your entry.client.tsx file
89
- import { RemixBrowser } from " @remix-run/react " ;
85
+ import { HydratedRouter } from " react-router/dom "
90
86
import { startTransition , StrictMode } from " react" ;
91
87
import { hydrateRoot } from " react-dom/client" ;
92
88
@@ -99,7 +95,7 @@ startTransition(() => {
99
95
hydrateRoot (
100
96
document ,
101
97
<StrictMode >
102
- < RemixBrowser / >
98
+ < HydratedRouter / >
103
99
< / StrictMode >
104
100
);
105
101
});
@@ -110,15 +106,15 @@ You can use the `configureGlobalCache` function to override the libraries defaul
110
106
111
107
If you want to have a per route adapter you can use the ` createCacheAdapter ` to create an adapter and provide it to your hooks and functions.
112
108
113
- ``` ts
109
+ ``` tsx
114
110
115
111
import { createCacheAdapter , useCachedLoaderData } from " remix-client-cache" ;
112
+ import type { Route } from " ./+types/_index" ;
116
113
117
114
const { adapter } = createCacheAdapter (() => localStorage ); // uses localStorage as the cache adapter
118
115
119
-
120
116
// Caches the loader data on the client
121
- export const clientLoader = (args : ClientLoaderFunctionArgs ) => cacheClientLoader (args , {
117
+ export const clientLoader = (args : Route . ClientLoaderArgs ) => cacheClientLoader (args , {
122
118
// We pass our custom adapter to the clientLoader
123
119
adapter
124
120
});
@@ -142,8 +138,7 @@ export default function Index() {
142
138
{ user .description }
143
139
</div >
144
140
);
145
- }
146
-
141
+ }
147
142
148
143
```
149
144
@@ -189,6 +184,32 @@ const { adapter } = createCacheAdapter(() => new DatabaseAdapter()); // uses you
189
184
190
185
## API's
191
186
187
+ ### CacheRoute
188
+ Wrapper function that wraps your component and provides the loader data to it. It takes two arguments, the component that is wrapped as the first one, and the config options as the second (like the adapter to use).
189
+
190
+ ``` tsx
191
+ import { CacheRoute , createClientLoaderCache } from " remix-client-cache" ;
192
+ import type { Route } from " ./+types/_index" ;
193
+
194
+ // Caches the loader data on the client
195
+ export const clientLoader = createClientLoaderCache <Route .ClientLoaderArgs >();
196
+
197
+ // Wraps the component and provides the loader data to it that gets hot swapped behind the scenes
198
+ export default CacheRoute (function Index({ loaderData }: Route .LoaderData ) {
199
+ const { user } = loaderData ;
200
+ return (
201
+ <div >
202
+ { user .name } <hr /> { user .email }
203
+ <hr />
204
+ { user .username }
205
+ <hr />
206
+ { user .website } <hr />
207
+ { user .description }
208
+ </div >
209
+ );
210
+ })
211
+ ```
212
+
192
213
### createCacheAdapter
193
214
194
215
Function that creates a cache adapter and returns it. It takes one argument, the ` adapter ` that is used to store the data.
@@ -222,20 +243,20 @@ It takes two arguments, the first one is the `ClientLoaderFunctionArgs` object t
222
243
223
244
224
245
``` tsx
225
- import { json , type LoaderFunctionArgs } from " @remix-run/node" ;
226
- import { ClientLoaderFunctionArgs } from " @remix-run/react" ;
246
+
227
247
import { cacheClientLoader , useCachedLoaderData } from " remix-client-cache" ;
248
+ import type { Route } from " ./+types/_index" ;
228
249
229
- export const loader = async ({ params }: LoaderFunctionArgs ) => {
250
+ export const loader = async ({ params }: Route . LoaderArgs ) => {
230
251
const response = await fetch (
231
252
` https://jsonplaceholder.typicode.com/users/${params .user } `
232
253
);
233
254
const user = await response .json ();
234
255
await new Promise ((resolve ) => setTimeout (resolve , 1000 ));
235
- return json ( { user: { ... user , description: Math .random () } }) ;
256
+ return { user: { ... user , description: Math .random () } };
236
257
};
237
258
238
- export const clientLoader = (args : ClientLoaderFunctionArgs ) => cacheClientLoader (args , {
259
+ export const clientLoader = (args : Route . ClientLoaderArgs ) => cacheClientLoader (args , {
239
260
type: " swr" , // default is swr, can also be set to normal
240
261
key: " /user/1" // default is the current route path including search params and hashes
241
262
adapter : () => localStorage // default is the in memory adapter, can be anything your wish
@@ -250,11 +271,12 @@ Creates everything needed to cache the data via clientLoader, behind the scenes
250
271
251
272
``` tsx
252
273
import { createClientLoaderCache , cacheClientLoader } from " remix-client-cache" ;
274
+ import type { Route } from " ./+types/_index" ;
253
275
254
276
export const clientLoader = createClientLoaderCache ();
255
277
256
278
// above is equivalent to:
257
- export const clientLoader = (args : ClientLoaderFunctionArgs ) => cacheClientLoader (args );
279
+ export const clientLoader = (args : Route . ClientLoaderArgs ) => cacheClientLoader < Route . ClientLoaderArgs > (args );
258
280
clientLoader .hydrate = true ;
259
281
```
260
282
@@ -263,20 +285,19 @@ clientLoader.hydrate = true;
263
285
Used to remove the data that is piped from the loader to your component using the ` clientLoader ` export.
264
286
265
287
``` tsx
266
- import { json , type LoaderFunctionArgs } from " @remix-run/node" ;
267
- import { ClientLoaderFunctionArgs } from " @remix-run/react" ;
268
288
import { decacheClientLoader , useCachedLoaderData } from " remix-client-cache" ;
289
+ import type { Route } from " ./+types/_index" ;
269
290
270
- export const loader = async ({ params }: LoaderFunctionArgs ) => {
291
+ export const loader = async ({ params }: Route . LoaderArgs ) => {
271
292
const response = await fetch (
272
293
` https://jsonplaceholder.typicode.com/users/${params .user } `
273
294
);
274
295
const user = await response .json ();
275
296
await new Promise ((resolve ) => setTimeout (resolve , 1000 ));
276
- return json ( { user: { ... user , description: Math .random () } }) ;
297
+ return { user: { ... user , description: Math .random () } };
277
298
};
278
299
// The data is cached here
279
- export const clientLoader = ( args : ClientLoaderFunctionArgs ) => cacheClientLoader ;
300
+ export const clientLoader = createClientLoaderCache < Route . ClientLoaderArgs >() ;
280
301
clientLoader .hydrate = true ;
281
302
// It is de-cached after a successful action submission via the clientAction export
282
303
export const clientAction = decacheClientLoader ;
@@ -296,9 +317,10 @@ the `cacheClientLoader` is augmented to work with `useCachedLoaderData` in mind
296
317
297
318
``` tsx
298
319
import { useCachedLoaderData } from " remix-client-cache" ;
320
+ import type { Route } from " ./+types/_index" ;
299
321
300
322
// Must be used together with cacheClientLoader
301
- export const clientLoader = (args : ClientLoaderFunctionArgs ) => cacheClientLoader (args , " swr" );
323
+ export const clientLoader = (args : Route . ClientLoaderArgs ) => cacheClientLoader < Route . ClientLoaderArgs > (args , " swr" );
302
324
clientLoader .hydrate = true ;
303
325
304
326
export default function Index() {
@@ -329,8 +351,9 @@ Hook used to get an SWR component that hot swaps the data for you. It takes one
329
351
330
352
``` tsx
331
353
import { useCachedLoaderData , useSwrData } from " remix-client-cache" ;
354
+ import type { Route } from " ./+types/_index" ;
332
355
333
- export const clientLoader = (args : ClientLoaderFunctionArgs ) => cacheClientLoader (args );
356
+ export const clientLoader = (args : Route . ClientLoaderArgs ) => cacheClientLoader < Route . ClientLoaderArgs > (args );
334
357
clientLoader .hydrate = true ;
335
358
336
359
export default function Index() {
@@ -391,6 +414,13 @@ export default function Index() {
391
414
}
392
415
```
393
416
417
+ ## Migration from v2 to v3
418
+
419
+ Some of the previous functions that didn't require type info now require ` Route.ClientLoaderArgs ` type info. Providing this info should be enough to get you up and running.
420
+
421
+
422
+
423
+
394
424
## Support
395
425
396
426
If you like the project, please consider supporting us by giving a ⭐️ on Github.
0 commit comments