Как использовать useEffect и useState для загрузки и отображения данных в React
Что проверяют
Умеете ли вы довести загрузку в эффекте до рабочего состояния, а не до демо: с ошибками, отменой и сменой параметров. Следом почти всегда спрашивают про гонку запросов и про то, зачем в продакшене берут TanStack Query.
Как отвечать
Каркас такой:
- три состояния: данные, загрузка, ошибка. Удобнее одним объектом со статусом
'idle' | 'loading' | 'success' | 'error', тогда невозможные комбинации вроде «загрузка и ошибка сразу» не возникают; - асинхронная функция внутри эффекта: колбэк
useEffectне делаютasync, потому что он должен вернуть функцию очистки или ничего, а не промис; - зависимости: в массив попадает всё, от чего зависит запрос, например
[userId]. При его смене эффект перезапустится, и индикатор загрузки нужно включить снова; - проверка ответа:
fetchне отклоняет промис на 404 и 500, поэтомуresponse.okпроверяется вручную; - отмена: в эффекте создаётся
AbortController, сигнал уходит вfetch, а очистка вызываетcontroller.abort(). ОшибкуAbortErrorв состояние не пишут.
Отдельно скажите про StrictMode: в режиме разработки React монтирует компонент, размонтирует и монтирует снова, поэтому эффект срабатывает дважды. Правильная очистка делает это безвредным, а отключать StrictMode ради одного запроса не нужно.
Сильный финал: документация React сама советует не писать загрузку в эффектах руками. В реальном проекте берут TanStack Query или SWR (кеш, дедупликация, повторы), а в Next.js App Router данные грузят в серверном компоненте.
Где спотыкаются
Не обрабатывают гонку. Пользователь быстро переключает профили, ответ на старый запрос приходит позже нового и затирает данные. Лечится отменой или флагом ignore в очистке.
Кладут в зависимости объект или функцию, которые создаются заново на каждом рендере. Эффект перезапускается бесконечно, а если внутри есть setState, получается цикл запросов.
Ставят loading в true только в начальном состоянии. При смене параметра старые данные висят без индикатора, и пользователь видит чужой профиль под новым заголовком.