> Как можно закэшировать данные useSWR, чтобы при возврате на страницу данные брались из кэша (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: Библио-Глобус

Стек: React

> Пример ответа

Короткий ответ

SWR автоматически кэширует данные в памяти и использует их при повторном монтировании компонента. Для сохранения кэша между сессиями или страницами используйте глобальный провайдер с localStorage или IndexedDB. Ключевые настройки: dedupingInterval для дедупликации запросов, revalidateIfStale для контроля обновления устаревших данных и provider для кастомного хранилища.

Подробное объяснение

SWR (stale-while-revalidate) по умолчанию хранит кэш в глобальном объекте cache внутри модуля. При повторном посещении страницы, если компонент с тем же ключом монтируется снова, SWR сначала возвращает закэшированные данные, затем выполняет фоновый ревалидацию. Однако этот кэш живёт только в памяти - при перезагрузке страницы он теряется.

Для персистентного кэширования нужно переопределить провайдер кэша через <SWRConfig value={{ provider }}>. Провайдер - это функция, возвращающая объект с методами get, set, delete и keys. Это позволяет подключить любое хранилище: localStorage, sessionStorage, IndexedDB или даже внешний кэш-сервис.

Важные параметры:

  • dedupingInterval (по умолчанию 2000ms) - предотвращает дублирующие запросы в течение интервала
  • revalidateIfStale (по умолчанию true) - если true, при наличии устаревшего кэша SWR сначала покажет его, затем обновит
  • revalidateOnMount - если false, при монтировании не будет делать новый запрос, если есть кэш
  • errorRetryCount - количество повторных попыток при ошибке

На практике

Для кэширования между страницами в SPA достаточно стандартного поведения SWR - кэш в памяти сохраняется, пока не произойдёт полная перезагрузка. Если нужно сохранять данные между сессиями (например, для офлайн-режима), используйте localStorage с ограничением по размеру (обычно 5-10MB) или IndexedDB для больших объёмов.

Типичный сценарий: при возврате на список товаров после просмотра детальной страницы данные должны быть из кэша, а не с сервера. Для этого:

  1. Убедитесь, что ключ SWR одинаковый (например, /api/products)
  2. Настройте revalidateIfStale: false и revalidateOnMount: false, если хотите полностью избежать повторного запроса
  3. Используйте fallbackData для начальных данных из другого источника

Для очистки кэша при выходе из системы или принудительного обновления используйте mutate(key, undefined, { revalidate: true }) или unstable_serialize для массовой очистки.

Пример кода

JSX
import useSWR, { SWRConfig } from 'swr';
// Кастомный провайдер с localStorage
const localStorageProvider = () => {
const map = new Map(JSON.parse(localStorage.getItem('swr-cache') || '[]'));
window.addEventListener('beforeunload', () => {
const appCache = JSON.stringify(Array.from(map.entries()));
localStorage.setItem('swr-cache', appCache);
});
return {
get: (key) => map.get(key),
set: (key, value) => map.set(key, value),
delete: (key) => map.delete(key),
keys: () => map.keys(),
};
};
// Глобальная конфигурация
function App({ children }) {
return (
<SWRConfig value={{
provider: localStorageProvider,
revalidateIfStale: false,
revalidateOnMount: false,
dedupingInterval: 5000
}}>
{children}
</SWRConfig>
);
}
// Компонент, использующий кэш
function ProductList() {
const { data, error } = useSWR('/api/products', fetcher);
if (error) return <div>Ошибка загрузки</div>;
if (!data) return <div>Загрузка...</div>;
return <div>{/* рендер списка */}</div>;
}

Как отвечать на собеседовании

Начните с объяснения, что SWR сам управляет кэшем в памяти, и при возврате на страницу данные берутся оттуда, если компонент не демонтировался. Затем уточните, что для сохранения кэша между сессиями нужно использовать кастомный провайдер. Упомяните trade-off между свежестью данных и производительностью. Покажите понимание параметров revalidateIfStale, revalidateOnMount и dedupingInterval. Если спросят про очистку кэша - расскажите про mutate и unstable_serialize.

Что проверяет интервьюер

Интервьюер проверяет понимание механизма кэширования SWR, умение настраивать персистентный кэш, знание lifecycle запросов и параметров конфигурации. Также оценивается способность объяснить trade-off между актуальностью данных и производительностью, и понимание, когда нужно отключать ревалидацию. Важно показать знание edge cases: что происходит при ошибке сети, как обрабатывать конфликты кэша, как чистить кэш при logout.

Типичные ошибки

  • Полагаться на то, что SWR сохраняет кэш между перезагрузками страницы без кастомного провайдера
  • Не учитывать, что при смене ключа кэш сбрасывается
  • Использовать localStorage без ограничения размера - это может привести к ошибке QuotaExceededError
  • Забывать очищать кэш при выходе из системы, что может привести к показу устаревших данных другому пользователю
  • Отключать ревалидацию (revalidateIfStale: false) без понимания последствий для актуальности данных
  • Не обрабатывать ошибки сериализации при сохранении в localStorage (например, circular references)

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью