Skip to content

Cache

💡

この機能を使用するには、最新のバージョン( ≥ 1.0.0 )にアップグレードしてください。

⚠️

ほとんどの場合、キャッシュを直接変更しないでください。予期しない動作が発生する可能性があります。キーを手動で変更する必要がある場合は、 SWR API の使用を検討してください。
参照:ミューテーション, テストケース間のキャッシュのリセット

デフォルトでは、 SWR はグローバルキャッシュを使用して、すべてのコンポーネント間でデータを保存および共有します。ただし、 SWRConfigprovider オプションを使用して、その挙動をカスタマイズできます。

キャッシュプロバイダーは、よりカスタマイズされたストレージで SWR を実現することを目的としています。

キャッシュプロバイダー

キャッシュプロバイダーは、次の TypeScript 定義( swr からインポート可能 )に一致する Map のようなオブジェクトです:

interface Cache<Data> {
get(key: string): Data | undefined
set(key: string, value: Data): void
delete(key: string): void
}

たとえば、JavaScript Map インスタンスを SWR のキャッシュプロバイダーとして直接使用できます。

キャッシュプロバイダーの作成

SWRConfigprovider オプションは、 キャッシュプロバイダーを返す関数を受け取ります。受け取ったプロバイダーは、その SWRConfig の範囲内のすべての SWR フックで使用されます。例:

import useSWR, { SWRConfig } from 'swr'
function App() {
return (
<SWRConfig value={{ provider: () => new Map() }}>
<Page/>
</SWRConfig>
)
}

<Page /> 内のすべての SWR フックは、その Map インスタンスから読み取りと書き込みを行います。また、特定のユースケースに合わせて、他のキャッシュプロバイダーの実装を使用することもできます。

💡

上記の例では、 <App /> コンポーネントが再マウントされると、プロバイダーも再生成します。キャッシュプロバイダーは、コンポーネントツリーの上位、またはレンダリングの外部に配置する必要があります。

ネストされている場合、 SWR フックは上位レベルのキャッシュプロバイダーを使用します。もし上位レベルのキャッシュプロバイダーが無い場合は、空の Map をデフォルトのキャッシュプロバイダーとして使用します。

⚠️

キャッシュプロバイダーを使用している場合、グローバルな mutate<SWRConfig /> 以下の SWR フックでは機能しません。代わりに こちら を使用してください。

現在のキャッシュプロバイダーにアクセスする

React コンポーネント内では、 mutate を含む他の設定と同様に、現在のキャッシュプロバイダーへアクセスするために、 useSWRConfig フックを使用する必要があります。

import { useSWRConfig } from 'swr'
function Avatar() {
const { cache, mutate, ...extraConfig } = useSWRConfig()
// ...
}

<SWRConfig> 以下でない場合は、デフォルトの設定を返します。

実験的:キャッシュプロバイダーの拡張

🧪

これは実験的な機能であり、将来のアップグレードで動作が変更される可能性があります。

複数の <SWRConfig> コンポーネントがネストされている場合、キャッシュプロバイダーを拡張できます。

provider の最初の引数は、上位レベルの <SWRConfig> のキャッシュプロバイダー( 親が <SWRConfig> でない場合はデフォルトのキャッシュ )です。これを使用して、キャッシュプロバイダーを拡張できます:

<SWRConfig value={{ provider: (cache) => newCache }}>
...
</SWRConfig>

正規表現から複数のキーを変更する

キャッシュプロバイダー API の柔軟性により、"部分的な変更"のヘルパーを構築することもできます。

以下の例では、 matchMutate はキーとして正規表現を受け取り、パターンに一致するものを変更するために使用できます。

function useMatchMutate() {
const { cache, mutate } = useSWRConfig()
return (matcher, ...args) => {
if (!(cache instanceof Map)) {
throw new Error('matchMutate requires the cache provider to be a Map instance')
}
const keys = []
for (const key of cache.keys()) {
if (matcher.test(key)) {
keys.push(key)
}
}
const mutations = keys.map((key) => mutate(key, ...args))
return Promise.all(mutations)
}
}

次に、コンポーネントの内部:

function Button() {
const matchMutate = useMatchMutate()
return <button onClick={() => matchMutate(/^\/api\//)}>
Revalidate all keys start with "/api/"
</button>
}
💡

この例では、キャッシュプロバイダーが Map インスタンスである必要があることに注意してください。

LocalStorage を使った永続キャッシュ

キャッシュを localStorage で同期しても良いかもしれません。実装例は次の通りです:

function localStorageProvider() {
// 初期化時に、 `localStorage` から Map にデータを復元します。
const map = new Map(JSON.parse(localStorage.getItem('app-cache') || '[]'))
// アプリが終了する前に、すべてのデータを `localStorage` に保存します。
window.addEventListener('beforeunload', () => {
const appCache = JSON.stringify(Array.from(map.entries()))
localStorage.setItem('app-cache', appCache)
})
// パフォーマンスのために、書き込みと読み取りには引き続き Map を使用します。
return map
}

次に、プロバイダーとして使用します:

<SWRConfig value={{ provider: localStorageProvider }}>
<App/>
</SWRConfig>
💡

改善点として、メモリキャッシュをバッファとして使用し、定期的に localStorage に書き込むこともできます。 IndexedDB または WebSQL を使用して同様の階層化キャッシュを実装することもできます。

テストケース間のキャッシュのリセット

アプリケーションをテストするときは、テストケース間で SWR キャッシュをリセットすることをオススメします。空のキャシュプロバイダーでアプリケーションをラップするだけです。 Jest の例を次に示します:

describe('test suite', async () => {
it('test case', async () => {
render(
<SWRConfig value={{ provider: () => new Map() }}>
<App/>
</SWRConfig>
)
})
})

キャッシュへアクセスする

警告:キャッシュに直接書き込むことはするべきではありません。予期しない動作が発生する可能性があります。

const { cache } = useSWRConfig()
cache.get(key) // キーの現在のデータを取得します。
cache.clear() // ⚠️ すべてのキャッシュをクリアします。 SWRは、再レンダリング時に再検証します。