> Какие техники кэширования существуют в React (React)

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

Компании: Spotware

Стек: React

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

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

В React кэширование применяется для оптимизации производительности: React.memo мемоизирует компонент, useMemo кэширует вычисления, useCallback - функции. Для данных используются React Query, SWR, Redux Toolkit с createEntityAdapter. На сервере - React Server Components и кэш Next.js. Ключевой trade-off: скорость vs актуальность данных и потребление памяти.

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

Кэширование в React решает две задачи: предотвращение лишних ререндеров и сокращение повторных вычислений или запросов.

На уровне компонентов:

  • React.memo - поверхностное сравнение пропсов, пропускает ререндер, если пропсы не изменились. Полезно для тяжелых компонентов, но не для всех - сравнение тоже стоит ресурсов.
  • useMemo - кэширует результат функции между рендерами, пока не изменятся зависимости. Используется для дорогих вычислений (фильтрация, сортировка больших массивов).
  • useCallback - кэширует саму функцию, часто для передачи в memo-компоненты или в списки зависимостей эффектов.

На уровне данных:

  • React Query (TanStack Query) - автоматическое кэширование ответов API с stale-while-revalidate стратегией, background refetch, инвалидация по ключам.
  • SWR - похожий подход, но с фокусом на revalidation on focus и interval refetch.
  • Redux Toolkit - createEntityAdapter нормализует данные, а createAsyncThunk с кэшированием через middleware.

На уровне сервера:

  • React Server Components - данные кэшируются на сервере, клиент получает готовый HTML, без повторных запросов.
  • Next.js - unstable_cache (или cache() в App Router) для кэширования fetch-запросов, ISR (Incremental Static Regeneration) для страниц.

Продвинутые техники:

  • Debounce и throttle для кэширования ввода (поиск, фильтры).
  • LRU cache (Least Recently Used) для ограничения размера кэша - библиотеки типа lru-cache.
  • Context splitting - разделение контекста на несколько, чтобы изменения в одной части не триггерили ререндер всей подписки.

На практике

Выбор техники зависит от сценария:

  • Для статичных UI-элементов (иконки, хедер) - React.memo.
  • Для вычислений на основе пропсов (например, отфильтрованный список) - useMemo.
  • Для колбэков в memo-компонентах - useCallback.
  • Для данных с сервера - React Query или SWR: они дают кэш с TTL, retry, optimistic updates.
  • Для глобального состояния с частыми обновлениями - Redux Toolkit с нормализацией и селекторами (reselect).
  • Для SSR/SSG - Next.js кэш на уровне фреймворка.

Важно: не мемоизировать всё подряд - это ухудшает читаемость и может увеличить потребление памяти. Кэширование должно быть обосновано профилированием (React DevTools Profiler, Chrome Performance tab).

Пример кода

JSX
// React.memo для компонента
const ExpensiveList = React.memo(({ items }) => {
return items.map(item => <div key={item.id}>{item.name}</div>);
});
// useMemo для вычислений
function FilteredList({ items, filter }) {
const filtered = useMemo(() => {
return items.filter(item => item.name.includes(filter));
}, [items, filter]);
return <ExpensiveList items={filtered} />;
}
// useCallback для передачи в memo-компонент
function Parent() {
const handleClick = useCallback((id) => {
console.log(id);
}, []);
return <Child onClick={handleClick} />;
}
// React Query с кэшированием
import { useQuery } from '@tanstack/react-query';
function UserProfile({ userId }) {
const { data } = useQuery({
queryKey: ['user', userId],
queryFn: () => fetch(`/api/users/${userId}`).then(res => res.json()),
staleTime: 5 * 60 * 1000, // 5 минут до устаревания
cacheTime: 30 * 60 * 1000, // 30 минут в кэше
});
return <div>{data?.name}</div>;
}

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

Начни с краткого перечисления техник, затем выбери одну-две для углубленного объяснения. Покажи понимание trade-off: например, React.memo полезен только если компонент ререндерится с теми же пропсами, иначе сравнение пропсов - лишняя работа. Упомяни, что кэширование данных лучше выносить в библиотеки (React Query), а не писать вручную через useState + useEffect. Если спросят про серверный рендеринг - расскажи про React Server Components и кэш Next.js. Избегай абсолютизации: "всегда используй memo" - плохой совет.

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

  • Понимание механизма ререндеров в React и как мемоизация на них влияет.
  • Умение выбирать правильную технику под задачу, а не применять шаблонно.
  • Знание современных библиотек для кэширования данных (React Query, SWR).
  • Осознание компромиссов: память vs скорость, сложность кода vs производительность.
  • Глубина: может ли кандидат объяснить, как работает stale-while-revalidate или LRU cache.

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

  • Мемоизация всего подряд без профилирования - ухудшает читаемость и может замедлить приложение из-за накладных расходов на сравнение.
  • Использование useMemo для простых вычислений (например, конкатенация строк) - избыточно.
  • Забывание указать зависимости в useMemo/useCallback - приводит к багам с устаревшими данными.
  • Применение React.memo к компонентам с пропсами-функциями без useCallback - мемоизация бесполезна.
  • Ручное кэширование данных через useState + useEffect вместо библиотек - ведет к race conditions и дублированию кода.
  • Игнорирование инвалидации кэша - пользователи видят устаревшие данные.

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

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