跳至內容
文件
進階
快取

快取

💡

升級至最新版本(≥ 1.0.0)以使用此功能。

⚠️

在大多數情況下,您不應直接「寫入」快取,這可能會導致 SWR 未定義的行為。如果您需要手動變更一個鍵,請考慮使用 SWR API。
另請參閱:變更在測試案例之間重設快取

預設情況下,SWR 使用全域快取來儲存並在所有元件之間共享資料。但您也可以使用 SWRConfigprovider 選項來自訂此行為。

快取供應器旨在讓 SWR 能夠使用更多自訂的儲存方式。

快取供應器

快取供應器是一個類似 Map 的物件,其符合以下的 TypeScript 定義(可以從 swr 導入)

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

例如,一個 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 元件內部時,您需要使用 useSWRConfig 鉤子來存取目前的快取供應器以及其他設定,包括 mutate

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

如果它不在任何 <SWRConfig> 之下,它將回傳預設設定。

實驗性:擴展快取供應器

🧪

這是一項實驗性功能,行為可能會在未來的升級中變更。

當多個 <SWRConfig> 元件巢狀時,可以擴展快取供應器。

provider 函式的第一個參數是較高層級的 <SWRConfig> 的快取供應器(如果沒有父 <SWRConfig>,則為預設快取),您可以使用它來擴展快取供應器

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

範例

基於 LocalStorage 的持久快取

您可能想要將您的快取同步到 localStorage。以下是一個範例實作

function localStorageProvider() {
  // When initializing, we restore the data from `localStorage` into a map.
  const map = new Map(JSON.parse(localStorage.getItem('app-cache') || '[]'))
 
  // Before unloading the app, we write back all the data into `localStorage`.
  window.addEventListener('beforeunload', () => {
    const appCache = JSON.stringify(Array.from(map.entries()))
    localStorage.setItem('app-cache', appCache)
  })
 
  // We still use the map for write & read for performance.
  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>
    )
  })
})

修改快取資料

🚨

您不應直接寫入快取,這可能會導致未定義的行為。

您可以使用 mutate 來修改快取。例如,您可以像下面這樣清除所有快取資料。

const { mutate } = useSWRConfig()
 
mutate(
  key => true, // which cache keys are updated
  undefined, // update cache data to `undefined`
  { revalidate: false } // do not revalidate
)

更多資訊可以在這裡找到。