Skip to content

Commit e1e4cb8

Browse files
committed
V3 with cached route api
1 parent 4b4350e commit e1e4cb8

File tree

10 files changed

+384
-466
lines changed

10 files changed

+384
-466
lines changed

README.md

Lines changed: 74 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,10 @@
77
![npm](https://img.shields.io/npm/dm/remix-client-cache?style=plastic)
88
![GitHub top language](https://img.shields.io/github/languages/top/Code-Forge-Net/remix-client-cache?style=plastic)
99

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" />
1111

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.
1612

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.
1914

2015
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.
2116

@@ -25,40 +20,41 @@ It comes with a default adapter that uses in memory storage to cache your data.
2520

2621
First party support for localStorage, sessionStorage and localforage packages. You can just provide them as the argument to `configureGlobalCache`.
2722

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+
2828
## Install
2929

30-
npm install remix-client-cache
30+
```bash
31+
npm install remix-client-cache
32+
```
3133

3234
## Basic usage
3335

3436
Here is an example usage of remix-client-cache with the default in memory adapter.
3537

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";
3941

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) => {
4344
const response = await fetch(
4445
`https://jsonplaceholder.typicode.com/users/${params.user}`
4546
);
4647
const user = await response.json();
4748
await new Promise((resolve) => setTimeout(resolve, 1000));
48-
return json({ user: { ...user, description: Math.random() } });
49+
return { user: { ...user, description: Math.random() } };
4950
};
5051

51-
5252
// 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>();
5754

58-
export default function Index() {
5955
// 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;
6258
return (
6359
<div>
6460
{user.name} <hr /> {user.email}
@@ -69,7 +65,7 @@ export default function Index() {
6965
{user.description}
7066
</div>
7167
);
72-
}
68+
})
7369

7470
```
7571

@@ -86,7 +82,7 @@ The `cacheLoaderData` will use the default memory cache adapter that comes with
8682

8783
```ts
8884
// Inside your entry.client.tsx file
89-
import { RemixBrowser } from "@remix-run/react";
85+
import { HydratedRouter } from "react-router/dom"
9086
import { startTransition, StrictMode } from "react";
9187
import { hydrateRoot } from "react-dom/client";
9288

@@ -99,7 +95,7 @@ startTransition(() => {
9995
hydrateRoot(
10096
document,
10197
<StrictMode>
102-
<RemixBrowser />
98+
<HydratedRouter />
10399
</StrictMode>
104100
);
105101
});
@@ -110,15 +106,15 @@ You can use the `configureGlobalCache` function to override the libraries defaul
110106

111107
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.
112108

113-
```ts
109+
```tsx
114110

115111
import { createCacheAdapter, useCachedLoaderData } from "remix-client-cache";
112+
import type { Route } from "./+types/_index";
116113

117114
const { adapter } = createCacheAdapter(() => localStorage); // uses localStorage as the cache adapter
118115

119-
120116
// Caches the loader data on the client
121-
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args, {
117+
export const clientLoader = (args: Route.ClientLoaderArgs) => cacheClientLoader(args, {
122118
// We pass our custom adapter to the clientLoader
123119
adapter
124120
});
@@ -142,8 +138,7 @@ export default function Index() {
142138
{user.description}
143139
</div>
144140
);
145-
}
146-
141+
}
147142

148143
```
149144

@@ -189,6 +184,32 @@ const { adapter } = createCacheAdapter(() => new DatabaseAdapter()); // uses you
189184

190185
## API's
191186

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+
192213
### createCacheAdapter
193214

194215
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
222243

223244

224245
```tsx
225-
import { json, type LoaderFunctionArgs } from "@remix-run/node";
226-
import { ClientLoaderFunctionArgs } from "@remix-run/react";
246+
227247
import { cacheClientLoader, useCachedLoaderData } from "remix-client-cache";
248+
import type { Route } from "./+types/_index";
228249

229-
export const loader = async ({ params }: LoaderFunctionArgs) => {
250+
export const loader = async ({ params }: Route.LoaderArgs) => {
230251
const response = await fetch(
231252
`https://jsonplaceholder.typicode.com/users/${params.user}`
232253
);
233254
const user = await response.json();
234255
await new Promise((resolve) => setTimeout(resolve, 1000));
235-
return json({ user: { ...user, description: Math.random() } });
256+
return { user: { ...user, description: Math.random() } };
236257
};
237258

238-
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args, {
259+
export const clientLoader = (args: Route.ClientLoaderArgs) => cacheClientLoader(args, {
239260
type: "swr", // default is swr, can also be set to normal
240261
key: "/user/1" // default is the current route path including search params and hashes
241262
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
250271

251272
```tsx
252273
import { createClientLoaderCache, cacheClientLoader } from "remix-client-cache";
274+
import type { Route } from "./+types/_index";
253275

254276
export const clientLoader = createClientLoaderCache();
255277

256278
// above is equivalent to:
257-
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args);
279+
export const clientLoader = (args: Route.ClientLoaderArgs) => cacheClientLoader<Route.ClientLoaderArgs>(args);
258280
clientLoader.hydrate = true;
259281
```
260282

@@ -263,20 +285,19 @@ clientLoader.hydrate = true;
263285
Used to remove the data that is piped from the loader to your component using the `clientLoader` export.
264286

265287
```tsx
266-
import { json, type LoaderFunctionArgs } from "@remix-run/node";
267-
import { ClientLoaderFunctionArgs } from "@remix-run/react";
268288
import { decacheClientLoader, useCachedLoaderData } from "remix-client-cache";
289+
import type { Route } from "./+types/_index";
269290

270-
export const loader = async ({ params }: LoaderFunctionArgs) => {
291+
export const loader = async ({ params }: Route.LoaderArgs) => {
271292
const response = await fetch(
272293
`https://jsonplaceholder.typicode.com/users/${params.user}`
273294
);
274295
const user = await response.json();
275296
await new Promise((resolve) => setTimeout(resolve, 1000));
276-
return json({ user: { ...user, description: Math.random() } });
297+
return { user: { ...user, description: Math.random() } };
277298
};
278299
// The data is cached here
279-
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader;
300+
export const clientLoader = createClientLoaderCache<Route.ClientLoaderArgs>();
280301
clientLoader.hydrate = true;
281302
// It is de-cached after a successful action submission via the clientAction export
282303
export const clientAction = decacheClientLoader;
@@ -296,9 +317,10 @@ the `cacheClientLoader` is augmented to work with `useCachedLoaderData` in mind
296317

297318
```tsx
298319
import { useCachedLoaderData } from "remix-client-cache";
320+
import type { Route } from "./+types/_index";
299321

300322
// 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");
302324
clientLoader.hydrate = true;
303325

304326
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
329351

330352
```tsx
331353
import { useCachedLoaderData, useSwrData } from "remix-client-cache";
354+
import type { Route } from "./+types/_index";
332355

333-
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args);
356+
export const clientLoader = (args: Route.ClientLoaderArgs) => cacheClientLoader<Route.ClientLoaderArgs>(args);
334357
clientLoader.hydrate = true;
335358

336359
export default function Index() {
@@ -391,6 +414,13 @@ export default function Index() {
391414
}
392415
```
393416

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+
394424
## Support
395425

396426
If you like the project, please consider supporting us by giving a ⭐️ on Github.

0 commit comments

Comments
 (0)