Skip to content

Latest commit

 

History

History
217 lines (162 loc) · 9.58 KB

cache.ru.mdx

File metadata and controls

217 lines (162 loc) · 9.58 KB

import { Callout } from 'nextra-theme-docs'

Кеш

Обновитесь до последней версии (≥ 1.0.0), чтобы использовать этот функционал. В большинстве случаев вы не должны напрямую _писать_ в кеш, поскольку это может вызвать неопределенное поведение SWR. Если вам нужно вручную изменить ключ, рассмотрите возможность использования API SWR.
См. также: [Мутация](/docs/mutation), [Сброс кеша между тестами](#сброс-кеша-между-тестами).

По умолчанию SWR использует глобальный кеш для хранения и обмена данными между всеми компонентами. Но вы также можете настроить это поведение с помощью опции provider в SWRConfig.

Cache providers are intended to enable SWR with more customized storages. Провайдеры кеша предназначены для включения SWR с более индивидуализированными хранилищами.

Провайдер кеша

Поставщик кеша — это объект типа Map, который соответствует следующему определению TypeScript (которое может быть импортировано из swr):

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

Например, экземпляр JavaScript Map можно напрямую использовать в качестве провайдера кеша для SWR.

Создание провайдера кеша

Опция provider в SWRConfig получает функцию, которая возвращает провайдер кеша. Затем провайдер будет использоваться всеми хукамми SWR в пределах SWRConfig. Например:

import useSWR, { SWRConfig } from 'swr'

function App() {
  return (
    <SWRConfig value={{ provider: () => new Map() }}>
      <Page/>
    </SWRConfig>
  )
}

Все хуки SWR внутри <Page/> будут читать и писать из этого экземпляра Map. Вы также можете использовать другие реализации поставщика кеша для вашего конкретного случая использования.

В приведённом выше примере, когда компонент `` повторно монтируется, провайдер также будет повторно создан. Провайдеры кеша должны быть размещены выше в дереве компонентов или вне рендеринга.

import { Cache } from '@components/diagrams/cache'

При вложенности, хуки SWR будут использовать провайдер кеша верхнего уровня. Если нет провайдера кеша верхнего уровня, он возвращается к провайдеру кэша по умолчанию, который является пустым Map.

Если используется провайдер кеша, глобальный `mutate` **не** будет работать для хуков 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>

Примеры

Мутация множества ключей из регулярных выражений (RegEx)

Благодаря гибкости API кеш-провайдера вы даже можете создать помощник «частичной мутации».

В приведенном ниже примере matchMutate может принимать регулярное выражение в качестве ключа и использоваться для мутации тех, кто соответствует этому шаблону.

function useMatchMutate() {
  const { cache, mutate } = useSWRConfig()
  return (matcher, ...args) => {
    if (!(cache instanceof Map)) {
      throw new Error('matchMutate требует, чтобы провайдер кеша был экземпляром Map')
    }

    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\//)}>
    Ревалидировать все ключи, начинающиеся на "/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('тестирование', async () => {
  it('тестовый пример', async () => {
    render(
      <SWRConfig value={{ provider: () => new Map() }}>
        <App/>
      </SWRConfig>
    )
  })
})

Доступ к кешу

Предупреждение: вы не должны писать в кеш напрямую, это может привести к неопределенному поведению.

const { cache } = useSWRConfig()

cache.get(key) // Получить текущие данные для ключа.
cache.clear()  // ⚠️ Очистить весь кеш. SWR проведёт ревалидацию при повторном рендеринге.