Загрузка данных при монтировании
Получайте JSON из API внутри useEffect, сохраняйте ответ в состоянии и запускайте получение только один раз с пустым массивом зависимостей.
«Загрузка данных при монтировании» — бесплатный урок Frontend Academy на CoddyKit. Это урок 2 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.
Шаблон получения данных
Стандартный шаблон получения данных в React: 1) определите состояние загрузки, ошибки и данных, 2) выполните запрос в useEffect с пустым массивом зависимостей [], 3) обновите состояние в функции обратного вызова, 4) отображайте интерфейс на основе состояния.
Полный пример
Полный пример получения пользователей при монтировании с обработкой состояний загрузки и ошибки.
interface User { id: number; name: string; email: string; }
function UserList() {
const [users, setUsers] = useState<User[]>([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
fetch('/api/users')
.then(res => {
if (!res.ok) throw new Error(`HTTP ${res.status}`);
return res.json();
})
.then(data => setUsers(data))
.catch(err => setError(err.message))
.finally(() => setLoading(false));
}, []);
if (loading) return <Spinner />;
if (error) return <ErrorMessage message={error} />;
return <ul>{users.map(u => <UserItem key={u.id} {...u} />)}</ul>;
}Использование async/await в useEffect
Функция обратного вызова useEffect не может напрямую быть async: в этом случае она вернула бы промис, который React воспринял бы как функцию очистки. Вместо этого определите внутреннюю асинхронную функцию и немедленно вызовите её.
useEffect(() => {
async function fetchUsers() {
try {
const res = await fetch('/api/users');
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
setUsers(data);
} catch (err) {
setError((err as Error).message);
} finally {
setLoading(false);
}
}
fetchUsers();
}, []);Проверка статуса ответа
fetch не выбрасывает исключения при HTTP-ошибках (4xx, 5xx) — только при сбоях сети. Всегда проверяйте response.ok и вручную выбрасывайте исключение для ошибочных ответов.
const res = await fetch('/api/data');
if (!res.ok) {
// Could also use res.status for specific handling
throw new Error(`Server responded ${res.status}: ${res.statusText}`);
}
const data = await res.json();Получение данных при изменении зависимости
Добавьте зависимость (например, ID из параметров маршрута или свойств) в массив зависимостей эффекта. Эффект будет запускаться снова и получать свежие данные всякий раз, когда зависимость изменяется.
const { userId } = useParams();
useEffect(() => {
if (!userId) return;
setLoading(true);
fetch(`/api/users/${userId}`)
.then(r => r.json())
.then(setUser)
.finally(() => setLoading(false));
}, [userId]);POST-запросы в эффектах
Эффекты также могут отправлять запросы POST/PUT/DELETE, но обычно они запускаются событиями (отправкой формы или нажатием кнопки), а не эффектами при монтировании. Оставляйте эффекты для загрузки данных, а для изменения данных используйте обработчики событий.
Пользовательский хук useFetch
Вынесите шаблон запроса, состояния загрузки и обработки ошибок в пользовательский хук, чтобы повторно использовать его в разных компонентах.
function useFetch<T>(url: string) {
const [data, setData] = useState<T | null>(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
setLoading(true);
fetch(url)
.then(r => { if (!r.ok) throw new Error(`${r.status}`); return r.json(); })
.then(setData)
.catch(e => setError(e.message))
.finally(() => setLoading(false));
}, [url]);
return { data, loading, error };
}Безопасный разбор JSON
Всегда оборачивайте res.json() в try/catch — некорректный JSON вызывает SyntaxError. Внешний catch обработает эту ошибку, но знание её источника помогает при отладке.
Настройка базового адреса API
Не зашивайте адреса API в код. Используйте переменные окружения (import.meta.env.VITE_API_URL) для базового адреса. Создайте центральный файл api.ts с настроенной оболочкой для запросов.
const API_BASE = import.meta.env.VITE_API_URL;
async function apiFetch<T>(path: string): Promise<T> {
const res = await fetch(`${API_BASE}${path}`, {
headers: { 'Authorization': `Bearer ${getToken()}` }
});
if (!res.ok) throw new Error(`API error ${res.status}`);
return res.json();
}Когда переходить на React Query
Ручные шаблоны запросов подходят для простых случаев. Когда Вам нужны кэширование, фоновое повторное получение данных, разбиение на страницы или изменения данных, перейдите на React Query (TanStack Query) — он надёжно обрабатывает все эти задачи.
Отображение скелетона загрузки
Вместо индикатора загрузки показывайте скелетон-интерфейс, соответствующий форме загруженного содержимого. Это уменьшает воспринимаемое время загрузки и предотвращает смещение макета.
Быстрая проверка
Почему нельзя сделать функцию обратного вызова useEffect напрямую асинхронной?
Повторение: получение данных в useEffect
Определяйте состояние загрузки, ошибки и данных. Выполняйте запрос в useEffect с пустым массивом зависимостей []. Определяйте внутреннюю асинхронную функцию — не делайте функцию обратного вызова асинхронной. Всегда проверяйте res.ok. Добавляйте URL/ID в зависимости для динамического получения данных. Для повторного использования выносите логику в пользовательский хук useFetch. Для получения данных в рабочем приложении рассмотрите TanStack Query.
Часто задаваемые вопросы
Урок «Загрузка данных при монтировании» бесплатный?
Да — полный текст урока «Загрузка данных при монтировании» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.
Чему я научусь в уроке «Загрузка данных при монтировании»?
Получайте JSON из API внутри useEffect, сохраняйте ответ в состоянии и запускайте получение только один раз с пустым массивом зависимостей. Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Frontend Academy?
Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 2 из 4.
Сколько времени занимает урок «Загрузка данных при монтировании»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Frontend Academy?
Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Основы useEffect: зависимости и очистка
- Загрузка данных при монтировании
- Обработка состояний загрузки и ошибки
- AbortController для очистки