Есть ли что-то встроенное в useFetch чтобы он не вызывался сразу?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Отложенный вызов в useFetch хуке
Вопрос о том, есть ли встроенные механизмы в useFetch для отложения выполнения запроса. Это важная тема, потому что не всегда нужно загружать данные сразу при монтировании компонента.
Проблема
В React хуки с побочными эффектами обычно выполняются при монтировании:
// Это выполняется сразу при монтировании
const { data, loading } = useFetch('/api/users');
Но иногда нам нужно выполнить запрос только по требованию:
- При клике пользователя на кнопку
- При ввода в поле поиска
- При заполнении формы
- При переходе на определённую вкладку
Стандартные подходы
Подход 1: Параметр enabled (React Query, SWR)
Если вы используете react-query или swr, они имеют встроенный механизм:
import { useQuery } from '@tanstack/react-query';
const { data, isLoading } = useQuery({
queryKey: ['users', userId],
queryFn: async () => {
const response = await fetch(`/api/users/${userId}`);
return response.json();
},
enabled: !!userId // Запрос выполнится только если userId существует
});
Подход 2: Кастомный useFetch с enabled флагом
Если вы пишете свой хук, добавьте параметр:
interface UseFetchOptions {
enabled?: boolean;
}
function useFetch<T>(url: string, options: UseFetchOptions = {}) {
const { enabled = true } = options;
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
if (!enabled) return; // Не выполняй если disabled
const fetchData = async () => {
setLoading(true);
try {
const response = await fetch(url);
const json = await response.json();
setData(json);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
};
fetchData();
}, [url, enabled]);
return { data, loading, error };
}
// Использование
const [userId, setUserId] = useState<string | null>(null);
const { data: user } = useFetch(`/api/users/${userId}`, {
enabled: !!userId // Загружать только если userId установлен
});
Подход 3: Возвращение функции для ручного вызова
Это более гибкий подход для полного контроля:
function useFetchManual<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<Error | null>(null);
const fetch = useCallback(async () => {
setLoading(true);
setError(null);
try {
const response = await fetch(url);
if (!response.ok) throw new Error('Network error');
const json = await response.json();
setData(json);
} catch (err) {
setError(err as Error);
} finally {
setLoading(false);
}
}, [url]);
return { data, loading, error, fetch }; // Возвращаем функцию!
}
// Использование
const SearchUsers = () => {
const { data: results, loading, fetch } = useFetchManual('/api/search');
const handleSearch = async (query: string) => {
// Запрос выполнится только при клике
await fetch(`/api/search?q=${query}`);
};
return (
<div>
<input onChange={(e) => handleSearch(e.target.value)} />
{loading && <p>Searching...</p>}
{results && <Results items={results} />}
</div>
);
};
Практический пример: Форма с отложенной загрузкой
interface User {
id: string;
name: string;
email: string;
}
function UserForm() {
const [userId, setUserId] = useState<string | null>(null);
const { data: user, loading } = useFetch(
userId ? `/api/users/${userId}` : null,
{ enabled: !!userId }
);
return (
<div className="space-y-4">
<select onChange={(e) => setUserId(e.target.value || null)}>
<option value="">Select a user</option>
<option value="1">User 1</option>
<option value="2">User 2</option>
</select>
{loading && <p>Loading...</p>}
{user && (
<div className="p-4 bg-surface-secondary rounded">
<h3>{user.name}</h3>
<p>{user.email}</p>
</div>
)}
</div>
);
}
Сравнение подходов
enabled флаг:
- Плюсы: просто, встроено в react-query
- Минусы: всё ещё нужен условный URL или обработка null
Ручная функция fetch:
- Плюсы: полный контроль, можно вызвать где угодно
- Минусы: больше кода, нужно самому управлять ошибками
Условный useEffect:
- Плюсы: понятен логика
- Минусы: нужно писать сам useEffect
Рекомендация
Для современного стека рекомендую:
- React Query / TanStack Query — лучший вариант для сложных запросов
- SWR — если нужно что-то более лёгкое
- Собственный хук — если хочешь обучиться или управлять параметрами
Вывод
Встроенных механизмов в базовом useFetch нет, но есть несколько проверенных способов:
- enabled флаг (React Query / SWR)
- Функция fetch (ручной вызов)
- Условный useEffect (собственная реализация)
Выбор зависит от требований вашего приложения и предпочтений команды.