Насколько хорошей практикой является вызов fetch внутри useEffect в React
Что проверяют
Отличаете ли вы «работает» от «так делают сегодня». Вызвать fetch в эффекте можно, и на учебном примере это верно. Но в продукте такой код обычно приезжает без отмены, без кеша и с гонками, поэтому вопрос на самом деле про то, знаете ли вы, какие задачи берёт на себя нормальный слой загрузки данных.
Как отвечать
Скажите прямо: допустимо, но это не выбор по умолчанию. Дальше перечислите, что придётся писать руками и о чём обычно забывают:
- гонка запросов: ответ на старый параметр приходит позже нового и затирает свежие данные. Лечится флагом в функции очистки или отменой через
AbortController; - состояния загрузки и ошибки, повтор после сбоя;
- отсутствие кеша и дедупликации: два компонента запросят одно и то же дважды;
- водопад: родитель загрузился, только после этого начинает загружаться ребёнок;
- эффекты не выполняются при серверном рендере, поэтому в разметке данных нет.
useEffect(() => {
let ignore = false;
fetch(url)
.then((r) => r.json())
.then((d) => { if (!ignore) setData(d); });
return () => { ignore = true; };
}, [url]);Сильный ответ называет альтернативы: во фреймворке данные грузятся на сервере, в обычном одностраничном приложении берут библиотеку кеширования запросов, которая закрывает дедупликацию, инвалидацию и фоновое обновление. Эффект остаётся для того, ради чего он есть: синхронизация с внешней системой, подписки, императивные API.
Где спотыкаются
Пишут эффект асинхронной функцией. Эффект должен вернуть функцию очистки или ничего, а асинхронная возвращает промис, и React очистку не получает. Асинхронность заворачивают внутрь.
Второе: объясняют очистку утечкой памяти и флагом «смонтирован ли компонент». Предупреждение про установку состояния после размонтирования из React убрали, реальная проблема другая: устаревший ответ ложится поверх свежего. И такой флаг не отменяет сам запрос.
Третье: кладут в зависимости объект или массив, собранный в теле компонента. Новая ссылка на каждом рендере даёт бесконечный цикл запросов: значение надо запомнить или разложить на примитивы.