That’s all it does. You can read the full code in the github repo (also check the pull requests to see the diffs and a running version of the app for each change we’ll do).

For this post, we only care about what’s in the App.js file:

We have an App component that receives a list of stocks and shows a . When a stock is selected from the table, the App component shows a for that stock.

What’s the problem? Well, we want our app to be blazing fast and show the as fast as possible, but we are making it wait until the browser downloads (and uncompresses and parses and compiles and runs) the code for .

Let’s see a trace of how long it takes to display the :

Trace without lazy loading

It takes 2470 ms to display the StockTable (with a simulated Fast 3G network and a 4x slowdown CPU).

As expected, we have react, react-dom, and some react dependencies. But we also have moment, lodash and victory, which we only need for , not for .

What could we do to avoid dependencies to slow down the loading of ? We lazy-load the component.

Lazy-loading a component

Using a dynamic import we can split our bundled javascript in two, a main file with just the code we need for displaying and another file with the code and the dependencies that needs.

This technique is so useful that React 16.6 added an API for making it easier to use with React components: React.lazy().

In order to use React.lazy() in our App.js we make two changes:

First we replace the static import with a call to React.lazy() passing it a function that returns the dynamic import. Now the browser won’t download ./StockChart.js (and its dependencies) until we render it for the first time.

But what happens when React wants to render and it doesn’t have the code yet? That’s why we added . It will render the fallback prop instead of its children until all the code of all its children is loaded.

React will start loading the first time the app is rendered, but this time it will actually try to render so if any other dependency (code or data) needs to be loaded it will be loaded.

We wrapped the lazy component inside a hiddendiv so it doesn’t show anything after it is loaded. And we wrapped that div inside another with a null fallback so it doesn’t show anything while it’s being loaded.

Note: hidden is the

HTML attribute for indicating that the element is not yet relevant. The browser won’t render elements with this attribute. React doesn’t do anything special with that attribute(but it may start giving hidden elements a lower priority in future releases).

What’s missing?

This last approach is useful in many cases but it has some problems.

First, the hidden attribute for hiding the rendered lazy component isn’t bulletproof. For example, the lazy component could use a portal which won’t be hidden (there is a hack that doesn’t require an extra div and also work with portals, but it’s a hack, it will break).

Second, even if the component is hidden we are still adding unused nodes to the DOM, and that could become a performance problem.

A better aproach would be to tell react to render the lazy component but without comitting it to the DOM after it’s loaded. But, as far as I know, it isn’t possible with the current version of React.

Another improvement we could do is to reuse the elements we are rendering when preloading the chart component, so when we want to actually display the chart React doesn’t need to create them again. If we know what stock the user will click we could even render it with the correct data before the user click it (like this).