Loading & Error UI in Next.js (loading.tsx, error.tsx, not-found.tsx)
When building modern web applications, user experience (UX) plays as big a role as performance. No one likes staring at a blank screen while waiting for content to load, nor being confused when something breaks without explanation. Next.js addresses these situations elegantly by allowing developers to create dedicated UI files:
-
loading.tsx
-
error.tsx
-
not-found.tsx
In this blog, we’ll explore how each of these works, why they matter, and how to implement them in your Next.js application.
1. Why Do We Need Dedicated UI States?
When working with server components, async rendering, or data fetching, there are three common UI scenarios:
-
Loading State: While waiting for server data or rendering, users should see a skeleton loader or spinner instead of a blank screen.
-
Error State: If something goes wrong (e.g., API failure, server crash), the user should see a friendly fallback UI.
-
Not Found State: When a route or resource doesn’t exist, the app should gracefully show a “404 Not Found” page.
Instead of cluttering your main components with extra logic, Next.js gives us special file-based conventions to handle these states.
2. loading.tsx
– Handling Loading States
The loading.tsx
file allows you to show fallback UI while a route or component is being rendered.
✅ Key Features:
-
Automatically displayed while server components are streaming.
-
Ideal for showing spinners, skeleton screens, or shimmer placeholders.
-
Once data is ready, it disappears and the actual content is displayed.
Example:
This ensures that when your /dashboard
page fetches data, users don’t face a blank screen but a friendly loading message.
3. error.tsx
– Handling Errors
Errors are inevitable—APIs fail, unexpected inputs occur, or code breaks. Instead of letting users see a crashed screen, Next.js allows you to define an error.tsx
file.
✅ Key Features:
-
Automatically rendered when an error occurs in the route.
-
You can reset errors using the
reset()
function provided in props. -
Useful for displaying error messages, retry buttons, or alternative suggestions.
Example:
Here, if your /dashboard
API fails, the user sees a graceful error UI instead of a broken page.
4. not-found.tsx
– Handling Missing Pages
When a requested page or resource doesn’t exist, you can create a custom 404 experience using not-found.tsx
.
✅ Key Features:
-
Automatically used when a route is not found.
-
You can also manually trigger it with
notFound()
function fromnext/navigation
. -
Perfect for 404 pages or showing “No data found” messages.
Example:
If a user tries to visit a non-existent route, they’ll see this UI.
5. Putting It All Together
Imagine you’re building a dashboard with data fetching:
-
While loading → show
loading.tsx
with a skeleton screen. -
If API fails → show
error.tsx
with retry option. -
If user requests a missing route → show
not-found.tsx
with a redirect link.
This approach makes your app resilient, user-friendly, and professional.
6. Best Practices
-
Always provide meaningful loading states (not just a spinner, but skeletons if possible).
-
Keep error messages clear and human-readable. Avoid exposing raw stack traces.
-
Design your not-found page to guide users back to a valid page (e.g., homepage, search bar).
-
Use consistent styling so that even errors feel like part of your brand.
Conclusion
The beauty of Next.js lies in its developer experience and UX-first design philosophy. With simple file-based conventions—loading.tsx
, error.tsx
, and not-found.tsx
—you can transform your app’s resilience, improve user trust, and reduce frustration.
Next time you build a route in Next.js, don’t forget to add these small but powerful UI states—they’ll make your app feel polished and complete. 🚀