Как правильно обрабатывать ошибку в хуке, если ошибка может быть строкой или объектом
Что проверяют
Понимаете ли вы, что в JavaScript выбросить можно что угодно, и умеете ли привести ошибку к одному виду до того, как она попадёт в стейт и в разметку. Следом спрашивают, как такая ошибка доходит до Error Boundary.
Как отвечать
Главная мысль: нормализовать ошибку в одном месте, а компонентам отдавать предсказуемую форму.
- тип
unknown: в TypeScript соstrictпеременная вcatchимеет типunknown. Сужайте её проверками, а не приведениемas Error; - функция нормализации:
toAppError(e: unknown)разбирает варианты по порядку.e instanceof Errorотдаётmessageиcause, строка оборачивается, объект со строковым полемmessage(частый формат тела ответа вроде{ message, code }) переносит поля, всё остальное превращается в общее сообщение, а оригинал уходит в лог; - единая форма в стейте: хук возвращает
{ data, error, isLoading }, где уerrorвсегда естьmessageи опциональноcodeиstatus; - ответы сервера:
fetchне отклоняет промис на 4xx и 5xx, проверяйтеresponse.okи читайте тело ошибки сами. У axios для этого естьaxios.isAxiosError(e)иe.response?.data; - отмена: создавайте
AbortControllerв эффекте, отменяйте запрос в функции очистки и игнорируйтеAbortError, иначе ответ старого запроса перезапишет стейт.
Error Boundary ловит только ошибки рендера, асинхронные ошибки из эффектов сами туда не попадают. Их показывают из стейта хука или пробрасывают в границу, например через showBoundary из react-error-boundary. В проекте с TanStack Query нормализацию делают один раз, в queryFn или в onError глобального QueryCache.
Где спотыкаются
Рендерят {error} напрямую. Строка отобразится, а объект уронит компонент с ошибкой Objects are not valid as a React child.
Обращаются к err.message, не проверив тип. У строки это undefined, и пользователь видит пустое место или слово «undefined».
Копируют нормализацию в каждый хук со своими проверками. Через полгода одна и та же ошибка сервера выглядит по-разному на трёх экранах.