> Как можно закэшировать данные 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 для больших объёмов.
Типичный сценарий: при возврате на список товаров после просмотра детальной страницы данные должны быть из кэша, а не с сервера. Для этого:
- Убедитесь, что ключ SWR одинаковый (например,
/api/products) - Настройте
revalidateIfStale: falseиrevalidateOnMount: false, если хотите полностью избежать повторного запроса - Используйте
fallbackDataдля начальных данных из другого источника
Для очистки кэша при выходе из системы или принудительного обновления используйте mutate(key, undefined, { revalidate: true }) или unstable_serialize для массовой очистки.
Пример кода
JSXimport useSWR, { SWRConfig } from 'swr';// Кастомный провайдер с localStorageconst 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)
> Похожие задачи по frontend
Каков порядок вывода в консоль в React-компоненте?
Синхронная или асинхронная функция setState в React и почему
Перерисуется ли React-компонент при изменении пропсов?
Почему рефы устанавливаются раньше полного рендера в React
> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?
Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью