> Как правильно обрабатывать асинхронные функции в useEffect и почему нельзя делать колбэк асинхронным (React)

Уровень: senior · Роль: frontend · Категория: Технические вопросы

Компании: ADV/web-engineering, Kaspersky, Сбер

Стек: React

> Пример ответа

В React колбэк, передаваемый в useEffect, не должен быть асинхронным напрямую, потому что useEffect ожидает возврата функции очистки (или undefined), а асинхронная функция неявно возвращает Promise, что может привести к непредсказуемому поведению и утечкам памяти.

Правильный подход - объявить асинхронную функцию внутри useEffect и сразу её вызвать:

JAVASCRIPT
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('/api/data');
const data = await response.json();
setData(data);
} catch (error) {
console.error('Ошибка загрузки:', error);
}
};
fetchData();
}, []); // пустой массив зависимостей - выполняется один раз при монтировании

Для обработки отмены запроса (например, при размонтировании компонента) используйте флаг или AbortController:

JAVASCRIPT
useEffect(() => {
const controller = new AbortController();
const signal = controller.signal;
const fetchData = async () => {
try {
const response = await fetch('/api/data', { signal });
if (!response.ok) throw new Error('Ошибка сети');
const data = await response.json();
setData(data);
} catch (error) {
if (error.name !== 'AbortError') {
console.error(error);
}
}
};
fetchData();
return () => controller.abort(); // функция очистки
}, []);

Почему нельзя делать колбэк асинхронным напрямую?

Если написать useEffect(async () => {...}), то колбэк вернет Promise, а React ожидает либо undefined, либо функцию очистки. Это вызовет предупреждение в консоли и может нарушить логику очистки эффекта, особенно при повторных рендерах или размонтировании компонента.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью