Add a touch of Suspense to your web app with React.lazy()
We’re all eagerly awaiting the arrival of React 17, which promises the much-anticipated Suspense and Time Splitting features. In the meantime, the React team have been generous enough to give us a sample of what’s in store, in the latest ‘minor’ update.
There’s a small platter of features that accompany React.lazy in 16.6 but I won’t talk about them here. When you finish reading this, go to the official React blog and have a look to see what’s good to use.
Code splitting is generally regarded as a good thing. It’s why the import
syntax has been pushed so heavily in the last few years. It’s also why Webpack and Next.js display it prominently on their home pages as a key feature. It’s compelling for good reason, why load all of the data in the webpage when the user might not need it? We want the perceived loading for our site to be consistently low and for users to only download the code that they need.
One way in which we can achieve this is through using dynamic imports. Unlike static imports, dynamic imports return a promise that gets resolved when necessary, allowing us to delay the loading of a module. A user’s journey may avoid using the aforementioned module entirely. Visually, dynamic imports vary from the more commonly seen static imports. The code snippet below highlights this:
Line 1 shows the syntax for static import, while line 3 shows the syntax for a dynamic import. It’s a little more verbose, and that’s because a dynamic import returns a promise that resolves to a module. Let’s see dynamic imports in action.
Say your web app is an Event Planner. You’ve got your CMS that contains all of the event details in a nice JSON object. You:
- Request the data
- Display a loading component
and either:
- Receive the data
- Render the event details
or:
- Receive an error
- Render an error component
Before using React.lazy, your code might look a little like this:
There’s nothing crazy going on here. We’re importing 3 components that get rendered under certain conditions. When our component mounts we make a request for our CMS data. Only when it returns successfully do we dynamically import our eventCards
component. We save the module to the state and load it within our render
method. The code on line 37 isn’t the clean React code we strive to achieve. We’re not using the declarative JSX syntax we know and love so much. Now imagine doing this with several components, it would make any sane JavaScript developer wince. We deserve better than that.
With React.lazy(), we can automatically load a given component’s code bundle only once we go to render the component:
Everything feels a little cleaner this time around. We’re returning normal looking JSX, and the React.lazy()
on line 12 makes our import logic a lot more declarative.
We had to make few notable changes to our code to lazy load our modules. The most significant is the use of the new Suspense
component that we’ve imported from React. The Suspense
component needs to be placed anywhere above our lazily-loaded module. If the module hasn’t fully loaded the fallback component is rendered in its stead. If you move your eyes up to line 27 you’ll see that I’ve taken the liberty of wrapping our Suspense
component in an ErrorBoundary
. If our EventCards
component fails or throws an error we let it propagate upwards and our ErrorBoundary
handles it. You can read more about ErrorBoundaries here, I didn’t go into anymore detail as it’s out of the article’s scope.
I’ve also gotten the Loading
component to render in two separate places. It’s included on line 24 as we wait for the data to come back from our request to the CMS. It is again included on line 28 as React goes to load the actual module.
Let me know in the comments about your thoughts new hese new features. Have you used it yourself in a different context? Then post a link of your repo, I’d love to check it out. React.lazy()
has just been released at the time of writing this article, so I’m certain I’ve barely scratched the surface of when and where to use it.
Thanks for reading!
It’s always exciting when the React teams gives us some shiny toys to tinker with, and with React 17 just around the corner we’ve got a lot more Suspense related features coming our way very soon.
If you’re interested in hosting me at a conference, meetup or as a speaking guest for any engagement then you can DM me on twitter!
I hope this article taught you something new. I post regularly, so if you want to keep up to date with my latest releases then you can follow me. And remember, the longer you hold the clap button, the more claps you can give. 👏👏👏
You an also check out my other articles below:
How to use Apollo’s brand new Query components to manage local state
No need to wait for the holidays, start Decorating now
Managing local state with Apollo and Higher Order Components
The React Conference drinking game
Develop and Deploy your own React monorepo app in under 2 hours, using Lerna, Travis and Now