Not every promise resolves.
Some are rejected.
So, when we use React.Suspense
to show loading and loaded states,
We need to consider exceptions as well.
Error Boundary Crash Course
Error boundaries were a flagship features of React 16 —
One of the first features to illustrate the potential of the fiber rewrite.
To use Suspense
effectively, you have to to make use of error boundaries
.
Start with Copy and Paste
The React docs have a copy and paste-able ErrorBoundary
component.
You really only need one of these things.
So copy and paste it into your code and customize to your needs.
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static defaultProps = {
fallback: <h1>Something went wrong.</h1>,
}
static getDerivedStateFromError(error) {
return { hasError: true }
}
componentDidCatch(error, errorInfo) {
console.log(error, errorInfo)
}
render() {
if (this.state.hasError) {
return this.props.fallback
}
return this.props.children
}
}
This one is customized slightly for demos.
- It assumes you don't have a logging service and uses
console.logs
- It takes a
fallback
prop for custom messages — much likeSuspense
Wrap Those Suspense Components
Wrap Suspense
components with an error boundary to
Handle these three possible states:
-
pending —
Suspense fallback
-
resolved —
Suspense children
-
rejected —
ErrorBoundary fallback
import React from "react"
import ErrorBoundary from "./error-boundary"
const LazyLoadedComponent = React.lazy(() => import("./SomeComponent"))
function MyApp() {
return (
<ErrorBoundary
fallback={
<div>Stop trying to make fetch happen. It's not gonna happen.</div>
}
>
<React.Suspense fallback={<div>Waiting...</div>}>
<LazyLoadedComponent />
</React.Suspense>
</ErrorBoundary>
)
}
This Ain't No 1:1
I see a lot of people immediately jump to wrapping ErrorBoundary
and Suspense
together.
It's not a good look.
Separate, they give you nuanced control over your entire view.
Stick layout components in between,
Handle errors closely,
Or have only one ErrorBoundary
around a bunch of Suspense
components.
The world is your oyster.
Keep 'em separate and keep control.
This is The Suspense API
Right now, we're using React.lazy
to do the work of communicating pending, resolved, and rejected states to our Suspense
and ErrorBoundary
components.
Next, we'll talk about creating our own wrappers to interact with this Suspense API.