Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як підтримувати кеш даних актуальним: інвалідація після мутацій і оновлення в реальному часі?

Кеш серверних даних корисний, доки він актуальний. Є три джерела змін, і кожне потребує свого механізму.

1. Зміни, зроблені самим користувачем (мутації). Після успішного запиту кеш, що залежить від змінених даних, треба оновити:

useMutation({
  mutationFn: createOrder,
  onSuccess: (order) => {
    queryClient.invalidateQueries({ queryKey: ['orders'] });          // позначити застарілим і перезапитати
    queryClient.setQueryData(['orders', order.id], order);            // покласти відповідь у кеш одразу
  },
});

invalidateQueries з префіксом ключа (['orders']) зачіпає всі запити, ключ яких з нього починається: списки з різними фільтрами, сторінки пагінації. Тому ієрархічні ключі (['orders', { status }], ['orders', id]) важливі з самого початку.

2. Зміни, зроблені іншими (інші користувачі, фонові задачі).

  • повторний запит при поверненні на вкладку (refetchOnWindowFocus, увімкнено за замовчуванням) і з інтервалом (refetchInterval) - простий варіант без інфраструктури;
  • події в реальному часі - WebSocket чи SSE (у Laravel - Reverb + Echo). Подія від сервера інвалідує чи оновлює кеш:
useEffect(() => {
  const channel = echo.private(`team.${teamId}`);
  channel.listen('OrderShipped', (event) => {
    queryClient.setQueryData(['orders', event.order.id], event.order);
    queryClient.invalidateQueries({ queryKey: ['orders'], exact: false, refetchType: 'active' });
  });
  return () => echo.leave(`team.${teamId}`);
}, [teamId, queryClient]);

setQueryData чи invalidateQueries:

  • setQueryData - коли подія містить повні актуальні дані: без додаткового запиту;
  • invalidateQueries - коли подія лише сигналізує «щось змінилося»: менше даних у повідомленні, але запит на сервер. refetchType: 'active' перезапитує лише те, що зараз на екрані, решта оновиться при наступному використанні.

3. Застарівання за часом - staleTime. Для кожного типу даних - свій: довідники (міста, категорії) - години, список замовлень - секунди, курс валют - хвилина.

Пастки:

  • шторм запитів: подія, що інвалідує широкий ключ, у тисячі відкритих вкладок одночасно - тисячі запитів на сервер. Варто передавати дані в самій події або додавати випадкову затримку;
  • порядок подій: подія може прийти раніше, ніж відповідь на мутацію в цій самій вкладці, - перевіряти версію (updated_at) перед записом у кеш;
  • авторизація каналів: приватні канали WebSocket мають перевіряти, чи користувач має доступ до даних, - інакше кеш отримає чужі дані.

Докладніше в документації: TanStack Query: інвалідація запитів

Схожі питання