React.Suspense
, along with React.lazy()
, introduced in v16.6, adds new functionality that allows components to wait for something before actually rendering. This new ability makes code splitting and lazy loading of React components a breeze!
To get started, you will need to make sure you are on React v16.6 or higher. If you’re starting a new project, or if you’re working with an older project that’s not on the correct version, simply:
# Via npm
$ npm install --save react react-dom
# Or via Yarn
$ yarn add react react-dom
And then within the component you’d like to handle lazy loading of other components, import both Suspense
and lazy
:
import React, { lazy, Suspense } from 'react';
It’s worth pointing out that while Suspense
and lazy
allows you to lazy load components quickly and easily, you may not see much benefit out of the gate if you are bundling your entire application up into a single script with something like Webpack.
While out of scope for this article, you can read up on code splitting with Webpack in the Webpack documentation.
React.lazy()
The lazy()
method takes a function as the first parameter which is expected to import
another component, like so:
const SomeComponent = lazy(() => import('./SomeComponent');
Because the import
is inside of a function passed to lazy()
, the loading of the component won’t happen until we actually use the component, instead of being eagerly loaded with the other imports at the top of your file.
React.Suspense
The React.Suspense
component allows us to wrap a component up and specify a fallback
component which will be shown while the wrapped component loads:
<Suspense fallback={<div>Loading...</div>}>
<SomeComponent />
</Suspense>
This is especially beneficial when you are loading components that are either on the large side, or happens to import
large libraries (like react-pdf
or react-draft-wysiwyg
).
Even if your components aren’t in the heavyweight division, lazy loading can help out your end users that may not have the best Internet connection.
To really get a feel for using React.Suspense
and React.lazy()
we are going to need two separate files. One is just our basic React app boilerplate, and the other is our component that will be lazy loaded.
Let’s start with the component we’re going to import
. For this example, I’ve created a very simple component that loads the always dapper Alligator.io logo:
import React from "react";
function AlligatorioLogo() {
const imageSource = "https://uploads.codesandbox.io/uploads/user"
+ "/39d6d9f6-60d2-4a60-9eb7-9250c3417bef"
+ "/saY6-alligatorio-logo.png";
return (
<img
alt="Alligator.io Logo"
src={imageSource}
width="250"
/>
);
}
export default AlligatorioLogo;
Next up is our App’s boilerplate code and a small bit of state logic so that we can manually trigger the loading of our component:
import React, { Component, Fragment, lazy, Suspense } from "react";
import { render } from "react-dom";
import "./styles.css";
const AlligatorioLogo = lazy(() => import("./AlligatorioLogo"));
class App extends Component {
constructor(props) {
super(props);
this.state = {
showLogo: false
};
}
onClick = () => {
this.setState({ showLogo: !this.state.showLogo });
};
render() {
return (
<div className="App">
<h1>React.lazy() + <React.Suspense /> Demo</h1>
<div>
<button onClick={this.onClick}>
{this.state.showLogo &&
<Fragment>Click to Hide the Logo</Fragment>
}
{!this.state.showLogo && (
<Fragment>Click to Show the Logo</Fragment>
)}
</button>
</div>
<hr />
{this.state.showLogo && (
<Suspense fallback={<div>Loading...</div>}>
<AlligatorioLogo />
</Suspense>
)}
</div>
);
}
}
const container = document.createElement("div");
document.body.appendChild(container);
render(<App />, container);
As you can see, there’s really not much to using Suspense
and lazy()
. Because of how simple it is, it shouldn’t be much of a burden to port existing systems to it, especially if you’re already splitting out your components into separate files.
The introduction of React.lazy()
and React.Suspense
is a wonderful step forward in helping to reduce the amount of boilerplate code you need to write to build a modern web application.
While already quite powerful, Suspense
isn’t without it’s shortcomings. The big missing piece, which is on the React Roadmap for a future v16 point release, is the ability to use Suspense
with data fetching.
Once this data fetching functionality is available, Suspense
will be able to wait for things like AJAX calls and show the fallback component while it loads.
It’s also worth noting that Suspense
isn’t quite ready for use with server-side rendering.
If you’re ready to give React.Suspense
and React.lazy()
a spin, you can head on over to CodeSandbox to see the code from this article in action!
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!