4.4 KiB
Coding 4
Error Handling
- To handle errors, another file is there named
error.jsx. - During development mode it will tell the detailed error ie where in the ocde there is error but in the production mode ie when we run
npm run buildthennpm run startthen we get different kind of error and to show specific message in that case Structure
src/app
products
[productId]
reviews
[reviewId]
error.jsx
page.jsx
page.jsx
In src/app/products/[productId]/reviews/[reviewId]/page.jsx
import { notFound } from "next/navigation";
function getRandomInt(count) {
return Math.floor(Math.random() * count);
}
export default function ReviewDetail(prop) {
console.log("params: ", prop.params);
if (Number(prop.params.reviewId) > 1000) {
notFound();
}
if (getRandomInt(2) == 1) {
throw new Error("error with review");
}
return (
<h1>
Review {prop.params.reviewId} about product {prop.params.productId}
</h1>
);
}
So to catch these errors and display them
In src/app/products/[productId]/reviews/[reviewId]/error.jsx
"use client";
export default function ErrorBoundary({ error }) {
return <div className="">Error in reviewId. Error is {error.message}</div>;
}
Make sure that error boundary is client component
- Automatically wrap a route segment and its nested children in a React Error Boundary
- Create error UI tailored to specific segments using the file-system heirarchy to adjust granularity
- Isolate errors to affected segments while keeping the rest of the application functional.
- Add functionality to attempt to recover from an error without a full page reload
Component Heirarchy
<Layout>
<Template>
<ErrorBoundary fallback={<Error />} >
<Suspense fallback={<Loading />}>
<ErrorBoundary fallback={<NotFound />} >
<Page />
</ErrorBoundary>
</Suspense>
</ErrorBoundary>
</Template>
</Layout>
Recovering from Errors
- In props of ErrorBoundary there is a property named error through which we can print error. Also there is one more field ie reset which tries to reload the component giving error in case it get resolved.
- In order for the error to get resolved the component which was giving error must be client component too so use
use client;at top inpage.jsx.
In src/app/products/[productId]/reviews/[reviewId]/error.jsx
"use client";
export default function ErrorBoundary({ error, reset }) {
return (
<div className="">
Error in reviewId. Error is {error.message} <br />
<button onClick={reset}>Try again</button>
</div>
);
}
Handling Errors in Nested Routes
- Errors bubble up to the closest parent error boundary
- An error.jsx file will cater to errors for all its nested child segments
- By positioning error.jsx files at different levels in the nested folders of a route , we can achieve a more granular level of error handling. Structure
src/app
products
[productId]
reviews
[reviewId]
error.jsx
page.jsx
page.jsx
So here error.jsx is at reviewsId so layout.jsx at products folder so layout.jsx of products will render but for reviews folder , it wont as error bondary is for reviewsId so all the upper parents component will render.
If we shift the error.jsx to products then products layout.jsx wont execute too.
Handling errors in Layout
- It is true that error.jsx file should be as close as to route as possible but unlike page.jsx layout component will render before error component so if error occurs in layout then error.jsx at same route/folder wont work.
- In such case error.jsx must be in parent folder for that route containing layout.jsx Structure
src/app
products
[productId]
layout.jsx
error.jsx
page.jsx
layout.jsx
In src/app/products/[productId]/layout.jsx
"use client";
function getRandomInt(count) {
return Math.floor(Math.random() * count);
}
export default function ProductIdLayout({ children }) {
if (getRandomInt(2) == 1) {
throw new Error("error with review");
}
return (
<>
<h2>Features Products</h2>
{children}
</>
);
}
In src/app/products/error.jsx
"use client";
export default function ErrorBoundary({ error, reset }) {
return (
<div className="">
Error in reviewId. Error is {error.message} <br />
<button onClick={reset}>Try again</button>
</div>
);
}