Типичные ошибки при работе с React Query
1. Неправильное использование QueryClientProvider
Вы, возможно, уже успели заметить, что QueryClientProvider — это не просто декоративный компонент, который добавляется в ваш index.tsx ради "красивой оболочки". Он предоставляет вашему приложению доступ к экземпляру QueryClient. И вот тут начинаются проблемы, если его пропустить.
Ошибка: вы не оборачиваете приложение в QueryClientProvider. Или ещё хуже, создаёте новый QueryClient в нескольких местах приложения (а то и внутри компонентов).
Симптомы: React Query просто не работает. Ваши запросы не кэшируются, а компоненты ведут себя так, как будто работают с одной большой дырявой сетью.
Как избежать: никогда не создавайте QueryClient внутри компонентов. Он должен быть один, создан на уровне корневого компонента. Используйте QueryClientProvider.
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App';
const queryClient = new QueryClient();
const Root = () => (
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
export default Root;
2. Пренебрежение типизацией запросов и мутаций
React Query славится своей продвинутой поддержкой TypeScript, но иногда разработчики полагаются на счастье (или магию) и игнорируют типизацию данных.
Ошибка: вы забываете типизировать ваши useQuery или useMutation, полагаясь на "как-нибудь разберётся".
Симптомы: куча предупреждений в редакторе, неожиданные ошибки типа "undefined is not a function" или "property does not exist".
Как избежать: используйте Generics для типизации данных запроса и ответа.
import { useQuery } from '@tanstack/react-query';
interface User {
id: number;
name: string;
}
const fetchUsers = async (): Promise<User[]> => {
const response = await fetch('/api/users');
if (!response.ok) {
throw new Error('Failed to fetch users');
}
return response.json();
};
// Типизированный хук с новым синтаксисом
const useFetchUsers = () => {
return useQuery<User[]>({
queryKey: ['users'],
queryFn: fetchUsers,
});
};
export default useFetchUsers;
Вы не только избежите ошибок, но и сделаете свой код понятным как вам, так и вашему будущему коллеге.
3. Использование некорректных ключей для запросов
Ключи запросов в React Query — это магический механизм, который помогает идентифицировать, кэшировать и обновлять данные. Но если вы используете неуникальные или неконсистентные ключи, то кэширование становится вашим врагом.
Ошибка: использование одинаковых ключей для разных запросов. Или попытка использовать сложные ключи без достаточной структуры.
Симптомы: один запрос затирает кэш другого. Данные "прыгают", показывая неправильные значения.
Как исправить: мтруктурируйте ключи запросов. Например, включайте идентификаторы сущностей или параметры.
const fetchUser = async (userId: number): Promise<User> => {
const response = await fetch(`/api/users/${userId}`);
if (!response.ok) {
throw new Error('Failed to fetch user');
}
return response.json();
};
const useFetchUser = (userId: number) => {
return useQuery<User>({
queryKey: ['user', userId],
queryFn: () => fetchUser(userId),
enabled: !!userId, // предотвращаем запрос, если userId невалиден
});
};
4. Переизбыток запросов из-за неправильного управления зависимостями
О, эта ошибка доставила боль не одному разработчику. useQuery и useMutation зависят от ключей и/или зависимостей, которые вы указали. Если вы добавляете в них что-то вроде "рандомных значений" или "переменных, которые меняются каждую секунду", ваши запросы будут выполняться бесконечно.
Ошибка: вы указываете зависимости, которые меняются слишком часто.
Симптомы: спам-запросы на сервер. React Query работает как бешеный принтер — запрашивает, запрашивает, запрашивает...
Как избежать: убедитесь, что ваши ключи и зависимости стабильны. Используйте staleTime для предотвращения лишних запросов.
const fetchData = async () => {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error('Failed to fetch data');
}
return response.json();
};
const useFetchData = () => {
return useQuery({
queryKey: ['data'],
queryFn: fetchData,
staleTime: 5000, // Данные считаются "свежими" в течение 5 секунд
});
};
5. Игнорирование обработки ошибок
Ошибка на сервере? Да ладно, не будем её обрабатывать — пользователь разберётся. Это, конечно, сарказм. Обработка ошибок — это половина успеха любого приложения.
Ошибка: вы не обрабатываете ошибки запросов.
Симптомы: пользователь видит пустой экран (или вечный спиннер) вместо внятного сообщения.
Как исправить: используйте onError и отображайте пользователю вменяемые сообщения.
const fetchData = async () => {
const response = await fetch('/api/data');
if (!response.ok) {
throw new Error('Failed to fetch data');
}
return response.json();
};
const useFetchData = () => {
return useQuery({
queryKey: ['data'],
queryFn: fetchData,
onError: (error: unknown) => {
console.error('Error fetching data:', error);
alert('Something went wrong. Please try again.');
},
});
};
6. Недостаточное внимание к производительности
React Query сам по себе оптимизированный инструмент. Но если злоупотреблять рефетчингом, кэшированием или игнорировать параметры вроде staleTime и cacheTime, можно получить медленное и неэффективное приложение.
Ошибка: вы вызываете refetch слишком часто или используете низкие значения для staleTime.
Симптомы: высокая нагрузка на сервер, медленное приложение.
Как исправить: анализируйте свои данные. Например, если данные редко обновляются, увеличьте staleTime.
const useFetchData = () => {
return useQuery({
queryKey: ['data'],
queryFn: fetchData,
staleTime: 60000, // Данные считаются свежими в течение 1 минуты
cacheTime: 300000, // Данные остаются в кэше в течение 5 минут
});
};
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ