Suspense Error Boundaries

Pro Members Only

This lesson is available if you have an active subscription.

Alternatively, some member might be able to gift it to you.

If you already have a subscription, you can sign in.

Professional NextJS Lessons

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
48.Incremental Static Regeneration (ISR) Simplified
⏱️ 2:51
🚨 Work In Progress 🚧
Subscribe for Launch

Suspense Error Boundaries

Subscription Required

You must have an active subscription to access this content.
If you already have a subscription, you can sign in.

Core Thinking

We’ve already explained how React Suspense lets you seamlessly show a fallback UI while data is loading and swaps it with the final user interface once all pending tasks have SUCCESSFULLY completed 🚀

But a critical thing you also need to consider is what happens if the loading fails or errors out 💥

Default Behaviour

If something you are waiting for errors out, it will result in the application crashing.

This is demonstrated in the below example where we try to compute the square root of negative numbers.

lib/SquareRoot.tsx
lib/SquareRootResult.tsx
"use client";

import { Suspense, useMemo, useState } from "react";
import { SquareRootResult } from "./SquareRootResult";
import { fetchSquareRoot } from "./api";

export const SquareRoot = () => {
const [value, setValue] = useState(0);
const promise = useMemo(() => fetchSquareRoot(value), [value]);

return (
<>
<input
type="number"
value={value}
onChange={(e) => {
setValue(+e.target.value);
}}
/>
<Suspense fallback={<div>Calculating...</div>}>
<SquareRootResult input={promise} />
</Suspense>
</>
);
};

Introducing Error Boundary

Just like suspense is used to show a fallback UI for pending states, the ErrorBoundary component is used to show a fallback UI for error states.

As a demonstration we can wrap the SquareRoot in a custom ErrorBoundary.

lib/SquareRootError.tsx
lib/SquareRoot.tsx
lib/SquareRootResult.tsx
'use client';

import { ErrorBoundary, FallbackProps } from "react-error-boundary";

function Fallback({ error, resetErrorBoundary }: FallbackProps) {
return (
<>
<div>Failed: {error.message}</div>
<button onClick={resetErrorBoundary}>Reset</button>
</>
);
}

export const SquareRootError = ({
children,
onReset,
}: React.PropsWithChildren<{ onReset: () => void }>) => {
return (
<ErrorBoundary FallbackComponent={Fallback} onReset={onReset}>
{children}
</ErrorBoundary>
);
};

Consolidating Error Handling

Just like Suspense pauses (shows fallback UI) for any children that might be pending, the ErrorBoundary shows fallback UI for any children that end up in an error state.

This si demonstrated in the below example where we use a general purpose ErrorBoundary for the entire page which allows the user to simply reload the page in case of error.

app/page.tsx
lib/PageError.tsx
import { PageError } from "@/lib/PageError";
import { SquareRoot } from "@/lib/SquareRoot";

export default function Page() {
return (
<div>
<h1>Square Root Calculators</h1>
<PageError>
<h2>Calculator 1:</h2>
<SquareRoot />
<hr />
<h2>Calculator 2:</h2>
<SquareRoot />
</PageError>
</div>
);
}
javascript
typescript
react
playwright

Enjoy free content straight from your inbox 💌

No spam, unsubscribe at any time.

Transcript

00:00

We've already explained how suspense lets you seamlessly show a fallback UI while data is loading and swaps it with the final user interface once all pending tasks have successfully completed. But a critical thing you also need to consider is what happens if the loading fails or errors out to demonstrate. We have a simple page that displays a square root component, and this is a component that we've looked at before. It collects a value from the user in a simple input, and then based on that value makes a fetch call to an API to fetch the square root. We pass that promise to the square root result component,

00:32

and while that promise is still pending, we show a fallback UI powered by a suspense boundary. The square root result component simply awaits that promise with use, which automatically integrates with the suspense boundary created by the parent. So within the application, as you modify the input, a new promise is created with the fetch for the result. And while that promise is pending, we see the suspense boundary calculating message. But what happens if that promise is rejected and we end up in an error situation? In this example, if we try to calculate the square root

01:04

of a negative number, which would actually result in an imaginary number, that is not something that this API can handle, and therefore the promise is rejected. We are not handling this case right now, which is why the application crashes and we end up with this error screen. Just like a suspense component is used to show a fallback UI for pending states, the error boundary component is used to show a fallback UI for error states. We've looked at error boundaries in our course on React, so let's create a simple error boundary specific to the square root component. We start off by marking this file with you client.

01:37

Because we plan to handle browser click events, we are using an NPM package called React Error boundary, so we don't have to create the core error boundary component ourselves for our fallback ui. The React error boundary package will provide us with the error along with the reset function. We simply display the error message to the user and then provide a simple button that when clicked will invoke the error boundary reset function. With this fallback UI in place, we create an error boundary component specific to the square root component. It'll accept the children, which will be displayed when there is no error, along with the reset function

02:10

that the user will be able to invoke to take them back to a known good state. Within our squa root component, we simply display the error boundary with the fallback wide to our custom fallback on reset wide to the past and reset function and the children contained within the error boundary. With this custom error boundary component created, we jump back to our square root component and then simply wrap the entire component with our custom error boundary. Note that it is nice to handle the errors and the pending states separately. As an example, in our particular error state, we don't want the user to mess around

02:41

with the input anymore, which is why our error boundary wraps the entire component, and suspense only wraps the result portion With our error now handled successfully, let's demonstrate this within the browser. If the user provides valid input, we see the pending state along with the final calculated result. However, if They provide an invalid value, an error occurs and we handle that gracefully within our error boundary, which displays the message to the user along with the option to reset the user interface to a known good state. Note that an error boundary should only be used for exceptional circumstances.

03:13

As an example. In this particular case, we could probably handle the negative numbers before making that API call. Just like suspense can handle pending states for any number of direct and indirect children, the error boundary will also action all unended errors for any of its sub-components. To demonstrate, we have a page that is going to display two square root calculators. These square root calculators are not handling their errors anymore. These are the original versions that do not contain an internal error boundary. So if you run this application within the browser, we see two square root calculators

03:46

and both will function fine as long as the provided value is valid. However, if either of them is passed in a negative value, the application will crash due to an unhandled promise rejection. We can create an error boundary for the entire page. We use the same fallback UI that we had before, which displays the error message along with the reset button and then specific to the page. We use the error boundary via to that fallback and with the reset function wire to simply reload the current page. This is a very general purpose error boundary as it simply displays the error message and provides the user with the button

04:18

that simply reloads the current page. We wrap both our square root calculators with this error boundary, and now when we jump into the application, as long as these components are behaving fine, we see the final result. But if an error occurs in either of these components or any of the children, you see this fallback user interface from here, the user can click the reset button to reload the page and start from fresh.

Professional NextJS

Professional NextJS

1.Course Intro
free
⏱️ 2:05
2.Get Setup
free
⏱️ 2:05
3.Project Template
free
⏱️ 5:45
4.Introducing FullStack React
free
⏱️ 4:57
5.App Router Reference
free
⏱️ 7:08
6.NextJS Server vs. "use client" Rendering
⏱️ 5:01
7.Nesting Server and Client Components
⏱️ 8:51
8.Client Only Components
⏱️ 3:48
9.Global CSS in NextJS
⏱️ 6:30
10.CSS Modules and SASS
⏱️ 4:15
11.Tailwind CSS
⏱️ 5:17
12.NextJS Custom Fonts
⏱️ 4:08
13.Static vs Dynamic Rendering
⏱️ 4:55
14.NextJS Link Component
⏱️ 3:20
15.NextJS Link Prefetching
⏱️ 5:49
16.Navigation Scroll with Link
⏱️ 2:02
17.Replace Navigation History
⏱️ 1:35
18.NextJS Image Component
⏱️ 7:01
19.Dynamic Image URLs
⏱️ 5:34
20.Safe Colocation with Private Folders
⏱️ 2:12
21.NextJS Route Groups
⏱️ 3:07
22.Dynamic Routes
⏱️ 5:37
23.NextJS API Routes
⏱️ 6:03
24.NextRequest and NextResponse
⏱️ 2:41
25.Cookies in API Handlers
⏱️ 4:25
26.React Suspense Simplified
⏱️ 2:23
27.Power of Suspense Boundaries
⏱️ 3:52
28.use Promises
⏱️ 3:24
29.Stream Promise Results from Server to Client
⏱️ 3:03
30.use Requires a Cached Promise
free
⏱️ 2:30
31.Suspense Error Boundaries
⏱️ 4:42
32.React Server Functions
⏱️ 4:50
33.Server Actions for Powerful Forms
⏱️ 5:35
34.useActionState to Simplify Form Actions
⏱️ 6:38
35.React Serializable Types
⏱️ 2:42
36.Create Dynamic Images with NextJS ImageResponse
⏱️ 5:54
37.Deploy NextJS Application to Production
⏱️ 3:51
38.NextJS Environment Variables Masterclass
⏱️ 3:50
39.Deploying and Managing Environment Variables
⏱️ 4:38
40.Using Databases for Dynamic Server Side State
free
⏱️ 7:34
41.Mastering NextJS Layout Files
⏱️ 4:54
42.Client State Management with NextJS
⏱️ 3:48
43.Client State Management In Action
⏱️ 8:04
44.Using Client State Management Libraries
⏱️ 5:25
45.Detecting Server vs Client Runtime and useEffect
⏱️ 4:33
46.Demystifying ISR vs SSR vs SSG
⏱️ 3:07
47.Static Site Generation or SSG with NextJS
⏱️ 3:16
48.Incremental Static Regeneration (ISR) Simplified
⏱️ 2:51
🚨 Work In Progress 🚧
Subscribe for Launch