← Усі статті

Офлайн у React: TanStack Query, IndexedDB і черга вихідних

Три кроки до стійких оптимістичних записів: кеш у IndexedDB, обробники мутацій і черга вихідних з ідентифікатором клієнта на Dexie.

Офлайн у React: TanStack Query, IndexedDB і черга вихідних
Зміст

Коротко

На Dev.to розібрали робочий рецепт офлайн-записів у React: TanStack Query як реактивний кеш, Dexie поверх IndexedDB і невелика черга вихідних. Мета — щоб додавання товару в «п’ятому ряду» пережило закриття застосунку і доїхало до сервера вже в автобусі. Три опори: зберегти кеш і призупинені мутації, зареєструвати обробники за замовчуванням, щоб їх можна було зібрати знову після перезапуску, і видавати клієнтські ідентифікатори плюс ідемпотентний повтор.

Що сталося

Користувач помічає не архітектуру, а поведінку: запис не зник після збою, слабкої мережі і вбитого процесу. Автор пропонує вважати TanStack Query дзеркалом локальної бази, а не єдиним місцем правди. Спочатку зміну пишуть у Dexie, потім оновлюють кеш запитів, а на сервер операція йде, коли зв’язок є. Це ближче до блокнота в кишені, ніж до форми, що живе лише поки відкрита вкладка: аркуш переживе розряд батареї, а список покупок можна переписати в систему вже вдома.

Перший крок — збереження реактивного кешу в IndexedDB через PersistQueryClientProvider і асинхронний persister. На старті застосунок піднімає узгоджений локальний знімок і викликає resumePausedMutations. Важливо виставити gcTime не коротшим за строк життя persister і через shouldDehydrateMutation зберігати лише ті призупинені мутації, які ви вмієте відновити. Інакше після перезапуску спливуть «зомбі»: запис є, а функції для повтору немає.

Другий крок — queryClient.setMutationDefaults зі стабільними ключами на кшталт ['items', 'create']. У збереженій мутації лежать змінні і метадані, але не замикання з mutationFn. Обробники за замовчуванням потрібно зареєструвати до виклику відновлення, зазвичай імпортом модуля під час завантаження застосунку. Третій крок — клієнтський ідентифікатор у onMutate, негайний запис у таблиці Dexie і запис у чергу вихідних із дією, ключем мутації, змінними і часом. Коли з’являється мережа, чергу дренують по порядку, на сервер іде заголовок на кшталт Idempotency-Key, успішні елементи з черги видаляють.

Чому це важливо

Звичайний оптимістичний інтерфейс без довговічного шару бреше користувачеві рівно до перезавантаження. Мережа «моргнула», вкладку закрили — і локальна правка зникла разом із пам’яттю процесу. Черга вихідних і ідентифікатор клієнта перетворюють повтор на безпечну операцію: сервер може отримати той самий запит двічі і не створити дублікат, якщо шанує ключ ідемпотентності.

Платформа теж диктує межі. Background Sync у Chrome допомагає, в iOS Safari — ні. Тому повтор при появі мережі, при поверненні вкладки і на старті застосунку потрібен як базовий контур, а не як опція. У кількох вкладках без вибору провідного процесу чергу оброблять двічі; BroadcastChannel або Web Locks тримають одного лідера. Експоненційний відкат із тремтінням закриває тимчасові збої, а постійні помилки перевірки (зазвичай відповіді 4xx) краще зняти з черги і показати людині, а не крутити нескінченно.

На практиці

Стаття дає зв’язку прийомів і начерки коду, не готовий пакет під ваш домен. Перед копіюванням вирішіть, що є джерелом правди для запису — локальна база чи кеш запитів.

  1. Пишіть у Dexie першим; хай TanStack Query реагує на зміну локальних даних.
  2. Зберігайте лише відновлювані призупинені мутації; без обробників за замовчуванням після перезапуску вони марні.
  3. Реєструйте setMutationDefaults до resumePausedMutations.
  4. Ставте клієнтський ідентифікатор і кладіть операцію в чергу вихідних у тому ж користувацькому жесті, що й оптимістичне оновлення.
  5. На сервері шануйте Idempotency-Key або номери послідовності, щоб повтор не плодив дублікати.
  6. Для пов’язаних сутностей відтворюйте чергу по порядку; дія create має прийти раніше за update.
  7. За кількох вкладок оберіть одного лідера для спорожнення черги.

Підсумок

Стійкий офлайн у React тут складається з трьох обіцянок: стан і черга переживають смерть процесу в IndexedDB, призупинені мутації можна зібрати знову за обробниками за замовчуванням, повтор безпечний завдяки клієнтським ідентифікаторам і дедуплікації на сервері. Мережа лишається ненадійною — але користувач продовжує працювати, бачить статус синхронізації і чекає доставки, коли з’являється зв’язок.

Коментарі

Завантаження коментарів…