loading.tsx работает благодаря streaming в App Router: Next.js сразу отдаёт layout и loading fallback, а реальный контент страницы стримится, когда async-работа завершится, и fallback заменяется.
Разбор
Вы получаете быстрый first paint и ощущение «оболочка → контент» без ручного useState(isLoading).
error.tsx обязан быть Client Component ('use client') — error boundaries опираются на client-side lifecycle. Два props: error (с .digest для корреляции с server logs) и reset (повторная попытка рендера segment). Важно: error.tsx ловит ошибки детей, не своего layout — чтобы поймать ошибку layout, boundary ставят на уровень выше.
Итог
Loading UI — автоматический Suspense через файл; error UI — client boundary с reset, размещённый на правильном уровне дерева.