Reatom VS react-query
Краткое сравнение ключевых API и поведения в @tanstack/react-query
и @reatom/async
.
TL;DR:
- В react-query (RQ) есть фичи, которых нет в reatom/async и наоборот.
- RQ имеет хорошие дефолты, но он менее гибкий.
- Инстансы RQ привязаны к жизненному циклу компонентов, что пораждает много проблем.
- reatom/async в 4 раза легче и имеет множество API для оптимизации производительности.
- reatom/async имеет лучшую экосистему, дебаг и логирование за счет Reatom.
Table of contents
Open Table of contents
Композиция и конфигурация
RQ позволяет включать или перенастраивать какие-то фичи с помощью существующих параметров. Reatom предоставляет примитивы с которыми разработчик может настроить что угодно.
// --- DATA FETCHING ---
// CONFIGURATION
export const useSomeQuery = () =>
useQuery({
queryKeys: ["some"],
keepPreviousData: true,
queryFn: async () => {
/* */
},
initialData: [],
select: ({ data }) => data.filter(el => el.image_id),
retry: (failureCount, error) =>
failureCount < 5 ? failureCount ** 10 : -1,
});
// COMPOSITION
export const fetchSome = reatomAsync(async () => {
/* */
}).pipe(
withAbort(),
withCache(),
withDataAtom([], (ctx, { data }) => data.filter(el => el.image_id)),
withRetry({
onReject: (ctx, error, retries) => (retries < 5 ? retries ** 10 : -1),
})
);
onConnect(fetchSome.dataAtom, fetchSome);
export const useSomeAtom = () => useAtom(fetchSome.dataAtom);
// --- DATA UPDATING ---
// CONFIGURATION (fails)
export const useSomeMutations = () => {
const queryClient = useQueryClient();
return useMutation({
mutationFn: async () => {
/* */
},
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ["some"] });
},
});
};
// COMPOSITION
export const updateSome = reatomAsync(async () => {
/* */
});
onUpdate(updateSome, fetchSome.invalidateCache);
export const useSomeUpdate = () => useAction(updateSome);
В примере выше видно, что useMutation
не имеет нужной конфигурации и код управления каким-то, достаточно типовым, поведением приходится писать самому. В Reatom все есть Atom
и мы можем легко настраивать нужное поведение с onUpdate
, получая правильные батчинги и умное логирование.
Конфигурация проще
Какие плюсы конфигурации?
- Конфигурация выглядит проще и требует меньше кода для типового использования, т.к. имеет какие-то дефолты.
- Она однозначна, читается и понимается легче. Не нужно импортировать дополнительные сущности.
- Объект конфигурации можно хранить отдельной константой.
Композиция эффективнее
Под композицией подразумевается наличие базовых примитивов (фабрики, операторов) и простой возможности связать их (pipe
, onUpdate
), что делает код немного больше, но намного гибче.
Что хорошего в композиции?
- Более гибкая настройка поведения каждой фичи.
- Операторы композиции можно переиспользовать не только над базовой сущностью, такой как
reatomAsync
, но и над собственной реализациейAsyncAction
. - Подход с конфигурацией делает невозможным tree shaking. При композиции, вспомогательные элементы не влияют на размер бандла и производительность, пока явно будут импортированы и использованы.
Разработчик библиотеки с конфигурацией должен всегда выбирать между гибкостью и сложностью: нужно либо очень много перегрузок, либо некоторые конфигурации будут невыразимы или принимать невозможные конфигурации (конфликтующие параметры). Пользователю библиотеки будет не очевидно с этим работать в не тривиальных случаях. На момент написания поста useQuery
принимает два параметра retry
и retryDelay
, в каждом из которых можно указывать число или функцию. Есть ли в них отличие и что будет если указать оба параметра (такое может быть, при переиспользовании какой-то конфигурации)? При композиции каждая фича имеет отдельную небольшую конфигурацию - это гибче и проще в каждом отдельном случае.
Инстанциирование (work in progress)
В реатоме инстанциирование более наглядное и предсказуемое, т.к. используется ссылка на переменную - результат reatomAsync
. В RQ используются ключи и в некоторых случаях это гибче для кеширования, но не типизируется и вообще никак не валидируется.
Цепочки (work in progress)
зависимые запросы очень примитивные https://tanstack.com/query/latest/docs/react/guides/dependent-queries
нет отмены цепочки запросов https://habr.com/ru/companies/ruvds/articles/725208/
проблема с саспенсом и параллельными запросами (актуально и для реатома в случае с onConnect?) (https://tanstack.com/query/latest/docs/react/guides/parallel-queries)
Производительность (work in progress)
@tanstack/react-query - 45.65KB -> 12.72KB (gzip)
@reatom/async - 8.04KB -> 3.24KB (gzip)