remix-client-cache

重要資訊
此程式庫現在是 React Router 生態系統的一部分,並在 React Router 之上運行。它應該與 remix.run 相容,但如果您遇到問題,1.1.0 版本是最後一個與 remix.run 相容的版本。
remix-client-cache 是一個功能強大且輕巧的程式庫,專為 Remix.run 設計,可使用 clientLoaders 在客戶端快取您的伺服器載入器資料。
預設情況下,它使用過時時重新驗證的策略,並在從伺服器載入後熱交換您的過時資訊。它還允許您使特定金鑰或多個金鑰的快取失效。
它允許您傳入您選擇的介面卡來快取您的資料。
它帶有一個預設介面卡,使用記憶體內儲存來快取您的資料。
對 localStorage、sessionStorage 和 localforage 套件的第一方支援。您可以將它們作為 configureGlobalCache
的參數提供。
安裝
npm install remix-client-cache
基本用法
這是 remix-client-cache 與預設記憶體內介面卡一起使用的範例。
import { json, type LoaderFunctionArgs } from "@remix-run/node";
import { ClientLoaderFunctionArgs } from "@remix-run/react";
import { cacheClientLoader, useCachedLoaderData } from "remix-client-cache";
export const loader = async ({ params }: LoaderFunctionArgs) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/users/${params.user}`
);
const user = await response.json();
await new Promise((resolve) => setTimeout(resolve, 1000));
return json({ user: { ...user, description: Math.random() } });
};
// Caches the loader data on the client
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args);
// make sure you turn this flag on
clientLoader.hydrate = true;
export default function Index() {
// The data is automatically cached for you and hot swapped when refetched
const { user } = useCachedLoaderData<typeof loader>();
return (
<div>
{user.name} <hr /> {user.email}
<hr />
{user.username}
<hr />
{user.website} <hr />
{user.description}
</div>
);
}
快取介面卡
該程式庫匯出一個您需要實作的介面,以建立您自己的快取介面卡。該介面稱為 CacheAdapter
。它與 Storage
的介面非常相似,並且要求您具有以下方法
getItem
:接收一個金鑰,並傳回一個 promise,該 promise 會解析為儲存在該金鑰處的值setItem
:接收一個金鑰和一個值,並傳回一個 promise,該 promise 會在值儲存時解析removeItem
:接收一個金鑰,並傳回一個 promise,該 promise 會在值移除時解析
cacheLoaderData
將使用程式庫隨附的預設記憶體快取介面卡。如果您想要進階的使用案例,請確保您提供的介面卡實作了 CacheAdapter
介面。
// Inside your entry.client.tsx file
import { RemixBrowser } from "@remix-run/react";
import { startTransition, StrictMode } from "react";
import { hydrateRoot } from "react-dom/client";
import { configureGlobalCache } from "remix-client-cache";
// You can use the configureGlobalCache function to override the libraries default in-memory cache adapter
configureGlobalCache(() => localStorage); // uses localStorage as the cache adapter
startTransition(() => {
hydrateRoot(
document,
<StrictMode>
<RemixBrowser />
</StrictMode>
);
});
您可以使用 configureGlobalCache
函數來覆寫程式庫的預設記憶體內快取介面卡。它會全域切換為您提供給它的任何介面卡。
如果您想要每個路由介面卡,您可以使用 createCacheAdapter
來建立介面卡,並將其提供給您的掛鉤和函數。
import { createCacheAdapter, useCachedLoaderData } from "remix-client-cache";
const { adapter } = createCacheAdapter(() => localStorage); // uses localStorage as the cache adapter
// Caches the loader data on the client
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args, {
// We pass our custom adapter to the clientLoader
adapter
});
// make sure you turn this flag on
clientLoader.hydrate = true;
export default function Index() {
const { user } = useCachedLoaderData<typeof loader>({
// We use the adapter returned by the createCacheAdapter function
adapter
});
return (
<div>
{user.name} <hr /> {user.email}
<hr />
{user.username}
<hr />
{user.website} <hr />
{user.description}
</div>
);
}
以下是一些如何將程式庫與不同的全域介面卡一起使用的範例。
configureGlobalCache(() => localStorage); // uses localStorage as the cache adapter
configureGlobalCache(() => sessionStorage); // uses sessionStorage as the cache adapter
configureGlobalCache(() => localforage); // uses localforage as the cache adapter
也適用於不同的每個路由介面卡
const { adapter } = createCacheAdapter(() => localStorage); // uses localStorage as the cache adapter
const { adapter } = createCacheAdapter(() => sessionStorage); // uses sessionStorage as the cache adapter
const { adapter } = createCacheAdapter(() => localforage); // uses localforage as the cache adapter
假設您想要使用一個自訂介面卡,使用資料庫來儲存資料。
您可以透過實作 CacheAdapter
介面,並將其傳遞給 configureGlobalCache
或 createCacheAdapter
函數來做到這一點。
class DatabaseAdapter implements CacheAdapter {
async getItem(key: string) {
// get the item from the database
}
async setItem(key: string, value: string) {
// set the item in the database
}
async removeItem(key: string) {
// remove the item from the database
}
}
configureGlobalCache(() => new DatabaseAdapter()); // uses your custom adapter as the cache adapter globally
const { adapter } = createCacheAdapter(() => new DatabaseAdapter()); // uses your custom adapter as the cache adapter per route
API
createCacheAdapter
建立快取介面卡並傳回它的函數。它接收一個引數,即用於儲存資料的 adapter
。
import { createCacheAdapter } from "remix-client-cache";
const { adapter } = createCacheAdapter(() => localStorage); // uses localStorage as the cache adapter
configureGlobalCache
設定全域快取介面卡的函數。它接收一個引數,即用於儲存資料的 adapter
。
import { configureGlobalCache } from "remix-client-cache";
configureGlobalCache(() => localStorage); // uses localStorage as the cache adapter
cacheClientLoader
用於快取從載入器傳輸到您的元件的資料,使用 clientLoader
匯出。
它接收兩個引數,第一個是傳遞到 clientLoader
函數的 ClientLoaderFunctionArgs
物件,第二個是具有以下屬性的物件
type
- 告知客戶端載入器是否應使用正常的快取機制,在其中儲存資料並提前傳回該資料,而不是重新擷取,或者是否應使用staleWhileRevalidate
機制,在其中傳回快取的資料並在背景中重新擷取。key
- 用於在快取中儲存資料的金鑰。預設為包含搜尋參數和雜湊的目前路由路徑。(例如 /user/1?name=John#profile)adapter
- 用於儲存資料的快取介面卡。預設為程式庫隨附的記憶體內介面卡。
import { json, type LoaderFunctionArgs } from "@remix-run/node";
import { ClientLoaderFunctionArgs } from "@remix-run/react";
import { cacheClientLoader, useCachedLoaderData } from "remix-client-cache";
export const loader = async ({ params }: LoaderFunctionArgs) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/users/${params.user}`
);
const user = await response.json();
await new Promise((resolve) => setTimeout(resolve, 1000));
return json({ user: { ...user, description: Math.random() } });
};
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args, {
type: "swr", // default is swr, can also be set to normal
key: "/user/1" // default is the current route path including search params and hashes
adapter: () => localStorage // default is the in memory adapter, can be anything your wish
});
clientLoader.hydrate = true;
decacheClientLoader
用於移除從載入器傳輸到您的元件的資料,使用 clientLoader
匯出。
import { json, type LoaderFunctionArgs } from "@remix-run/node";
import { ClientLoaderFunctionArgs } from "@remix-run/react";
import { decacheClientLoader, useCachedLoaderData } from "remix-client-cache";
export const loader = async ({ params }: LoaderFunctionArgs) => {
const response = await fetch(
`https://jsonplaceholder.typicode.com/users/${params.user}`
);
const user = await response.json();
await new Promise((resolve) => setTimeout(resolve, 1000));
return json({ user: { ...user, description: Math.random() } });
};
// The data is cached here
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader;
clientLoader.hydrate = true;
// It is de-cached after a successful action submission via the clientAction export
export const clientAction = decacheClientLoader;
接收一個可選的物件,其中包含以下屬性
key
- 用於在快取中儲存資料的金鑰。adapter
- 用於儲存資料的快取介面卡。
useCachedLoaderData
可用於從 clientLoader
匯出中取得快取資料的掛鉤。必須與 cacheClientLoader
一起使用,因為從 cacheClientLoader
傳回的資料經過擴充,可以在考慮 useCachedLoaderData
的情況下使用,而不是標準的 useLoaderData
掛鉤。
import { useCachedLoaderData } from "remix-client-cache";
// Must be used together with cacheClientLoader
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args, "swr");
clientLoader.hydrate = true;
export default function Index() {
// The data is automatically cached for you and hot swapped when refetched
const { user } = useCachedLoaderData<typeof loader>();
return (
<div>
{user.name} <hr /> {user.email}
<hr />
{user.username}
<hr />
{user.website} <hr />
{user.description}
</div>
);
}
接收一個可選的物件,其中包含以下屬性
-
adapter
- 用於儲存資料的快取介面卡。預設為程式庫隨附的記憶體內介面卡。
useSwrData
用於取得一個 SWR 元件的掛鉤,該元件會為您熱交換資料。它接收一個引數,即由 useCachedLoaderData
或 useLoaderData
掛鉤傳回的 loaderData。
import { useCachedLoaderData, useSwrData } from "remix-client-cache";
export const clientLoader = (args: ClientLoaderFunctionArgs) => cacheClientLoader(args);
clientLoader.hydrate = true;
export default function Index() {
// We do not destructure the data so we can pass in the object into the useSwrData hook
const loaderData = useLoaderData<typeof loader>();
// You can also use useCachedLoaderData hook with the useSwrData hook
const loaderData = useCachedLoaderData<typeof loader>();
// Pass the loader data into the hook and the component will handle everything else for you
const SWR = useSwrData(loaderData);
return (
<SWR>
{/** Hot swapped automatically */}
{({ user }) => (
<div>
{data.name} <hr /> {data.email}
<hr />
{data.username}
<hr />
{data.website} <hr />
{data.description}
</div>
)}
</SWR>
);
}
invalidateCache
可用於使特定金鑰的快取失效的實用程式函數。它接收一個引數,即用於在快取中儲存資料的 key
。也可以是金鑰陣列
import { invalidateCache } from "remix-client-cache";
invalidateCache("/user/1"); // invalidates the cache for the /user/1 route
請記住,這只能在客戶端上使用,因此可以在 clientLoader
或 clientAction
匯出或元件本身中使用。
useCacheInvalidator
傳回一個函數的掛鉤,該函數可用於使特定金鑰的快取失效。它接收一個引數,即用於在快取中儲存資料的 key
。也可以是金鑰陣列
import { useCacheInvalidator } from "remix-client-cache";
export default function Index() {
const { invalidateCache } = useCacheInvalidator();
return (
<div>
// invalidates the cache for the /user/1 route
<button onClick={ () => invalidateCache("/user/1") }>Invalidate cache</button>
</div>
);
}
支援
如果您喜歡該專案,請考慮在 Github 上給予 ⭐️ 來支援我們。
許可
MIT
錯誤
如果您發現錯誤,請在 我們在 GitHub 上的問題追蹤器 上提交問題
貢獻
感謝您考慮為 remix-client-cache 做出貢獻!我們歡迎任何大小的貢獻,包括錯誤報告、功能請求、文件改進或程式碼變更。
若要開始使用,請 fork 此儲存庫並在新的分支中進行變更。準備好提交變更後,請開啟一個 pull request,其中清楚說明您的變更以及任何相關問題或 pull request。
請注意,所有貢獻均受我們的 行為準則 約束。透過參與,您應遵守此準則。
我們感謝您為 remix-client-cache 做出貢獻,並幫助使其成為社群更好的工具,這表示您付出的時間和努力!