Как работать с loading и data из useQuery
Что проверяют
Понимаете ли вы разницу между первой загрузкой и фоновым обновлением и знаете ли, что data бывает undefined. Следом обычно спрашивают, чем isFetching отличается от isLoading и что показывать при ошибке, когда старые данные уже есть.
Как отвечать
Сначала уточните библиотеку. Чаще всего имеют в виду TanStack Query (пакет @tanstack/react-query, старый react-query остался на третьей версии). В Apollo Client флаг называется именно loading, в RTK Query есть isLoading и isFetching.
Для TanStack Query v5:
- сигнатура: только объект,
useQuery({ queryKey: ['user', id], queryFn }). Позиционные аргументы из старых примеров убраны; status:'pending','error'или'success'.isPendingозначает, что данных ещё нет;isFetching: идёт любой запрос, включая фоновый перезапрос при фокусе окна или послеinvalidateQueries;isLoading: в v5 этоisPending && isFetching, то есть первая загрузка, которая реально идёт;data:undefined, пока нет успешного ответа. После ошибки фонового обновления старыеdataсохраняются вместе сerror;placeholderData: keepPreviousData: оставляет прошлые данные при смене ключа, например при пагинации, аisPlaceholderDataподскажет, что они не свежие.
Порядок рендера обычно такой: если есть data, показываем их, а фоновую загрузку обозначаем ненавязчиво; если данных нет и есть ошибка, показываем ошибку с кнопкой refetch; иначе скелетон. С useSuspenseQuery загрузку и ошибку берут на себя Suspense и Error Boundary, а data типизирована как всегда определённая.
Стоит назвать умолчания: staleTime равен 0, gcTime 5 минут, retry 3 раза с экспоненциальной задержкой.
Где спотыкаются
Показывают спиннер по isFetching, и экран мигает при каждом возврате во вкладку.
Проверяют только isLoading и сразу пишут data.map. Для запроса с enabled: false в v5 isLoading ложно, данных нет, и компонент падает.
Ставят проверку ошибки выше данных. Одна неудачная фоновая попытка стирает с экрана уже загруженный список.