Cleaner React: Suspense

Faster Load Times

For another look at how we can clean up our React, let's take a look at React's Suspense feature and how we can use it to make apps load quicker. Simply put, a React app will load slower as its bundle size increases. This is bound to happen as you add more features, so what can we do?

Code Splitting

The process of breaking up an apps bundle into many files is code splitting. This allows you to only download the javascript you need for that initial render and the other javascript files are loaded as needed.

This is possible by using React.Suspense and React.lazy.

React.Suspense

Suspense lets components “wait” for something before rendering. Today, Suspense only supports one use case: loading components dynamically with React.lazy. In the future, it will support other use cases like data fetching.

Source: ReactJS Docs

A few things to note about using Suspense with React 16:

  • It is only available for the client; it cannot be used with ReactDOMServer.
  • In order to catch render errors you need to wrap Suspense with an Error Boundary.
  • In a future version of React, you will be able to use the Suspense feature for more things, like data fetching and also server rendering.

React.Lazy

React.lazy takes a function that returns a promise. So, when paired with React.Suspense, we can show a loader while we wait for things to resolve.

When we use these together with dynamic imports, it allows us to split up our application bundle into different files.

Code Example

Making a Lazy Component

Let's consider the component below.

```language-javascript

import React from "react";

const Thing = () => <div>Thing</div>

export default Thing;
```

We can make this a lazy loaded component using react.lazy and  dynamically loading it using import.

You can make it easier to find your chunk in the network tab by providing a comment as seen in the example. The chunk below would show up with the filename of "thing.chunk.js".

```language-javascript
const LazyThing = React.lazy(() =>
 import(
   /* webpackChunkName: "thing" */
   "./Thing"
 )
);
```

Using Lazy Component with Suspense

To render our lazy component we need to have React.Suspense somewhere above it in the tree. While the lazy component is loading, the loader component for the next Suspense up in the tree will be displayed.

```language-javascript
<React.Suspense fallback={<Loader />}>

   <LazyThing />

</React.Suspense>
```

Handling Errors

One last consideration is handling errors that may result when the lazy loaded component is loaded. This can crash the entire app, so we should add an Error Boundary component.

It is well documented how to create an Error Boundary in the Reacts Documentation.

Here's an example of how we would use an existing Error Boundary component called "Catch".

```language-javascript
<React.Suspense fallback={<Loader />}>  

<Catch>

 <React.Suspense fallback={<Loader />}>

   <LazyThing />

 </React.Suspense>

</Catch>
```

INTERACTIVE EXAMPLE

To see it in real life, I created an example app that uses all the things we discussed.

View Example App

View GitHub Repo

Faster Loading Apps

If you want a faster loading app, one thing you can do is reduce the initial bundle size by using code splitting.

One other thing to consider is analyzing your bundle size. You can read more on that here. By analyzing your bundle you can determine what other libraries might be bloating your bundle.

Happy bundle trimming!