Dev Highlights

Доки по разработке

This project is maintained by teniryte

5. Параллельные и зависимые запросы

В реальных приложениях часто нужно загружать несколько ресурсов одновременно или дожидаться завершения одного запроса перед запуском другого. TanStack Query v5 предлагает специализированные API.

Параллельные запросы через useQueries

import { useQueries } from '@tanstack/react-query';

const userDashboardQueries = (id: string) => [
  { ...userQuery(id) },
  { ...postsQuery(id), staleTime: 60_000 },
  { ...statsQuery(id), enabled: id !== 'guest' },
];

export function Dashboard({ userId }: { userId: string }) {
  const results = useQueries({ queries: userDashboardQueries(userId) });
  const [user, posts, stats] = results;

  if (user.isPending || posts.isPending) return <Skeleton />;
  return <DashboardView user={user.data} posts={posts.data} stats={stats.data} />;
}

combine для единого результата

const { data, pending, error } = useQueries({
  queries: [{ ...userQuery(id) }, { ...teamQuery(id) }],
  combine: results => ({
    data: {
      user: results[0].data,
      team: results[1].data,
    },
    pending: results.some(r => r.isPending),
    error: results.find(r => r.error)?.error,
  }),
});

combine вызывается при каждом изменении какого-либо результата, что упрощает мемоизацию.

Зависимые запросы (enabled)

const { data: user } = useQuery(userQuery(id));

const projects = useQuery({
  ...projectsQuery(user?.teamId),
  enabled: Boolean(user?.teamId),
});

enabled гарантирует, что второй запрос стартует только после получения параметров из первого. Нет нужды вручную проверять status.

suspense + зависимые запросы

При использовании useSuspenseQuery комбинируйте с useMemo, чтобы не запускать скрытых запросов:

const projectsQueryOptions = useMemo(() => {
  if (!user?.teamId) return undefined;
  return projectsQuery(user.teamId);
}, [user?.teamId]);

const projects = useSuspenseQuery(projectsQueryOptions);

Последовательные цепочки

const { data: sessionToken } = useQuery(sessionTokenQuery(), { gcTime: 0 });

const { data: profile } = useQuery({
  ...profileQuery(),
  enabled: Boolean(sessionToken),
  meta: { sessionToken },
});

meta можно использовать для проброса результата предыдущей операции во второй queryFn.

Отмена и координация

Примеры использования

  1. DashboarduseQueries для получения виджетов параллельно.
  2. Форма редактирования — основной объект + справочники (selectOptionsQuery).
  3. Мастер-детейл — детальный запрос включается enabled: Boolean(selectedId).
    • Динамический список идовuseQueries({ queries: ids.map(id => orderQuery(id)) }) + combine для нормализации.
    • Персональные рекомендации — основной пользователь, список интересов и отдельный запрос на офферы, включается только когда оба первые готовы.

Рекомендации