React Suspense and React.lazy by Example
React 16.6 was released this week and code splitting with Suspense is probably the most interesting feature included in my opinion.
React 16.6 is hot off the presses! đ±
â React.memo (like PureComponent but for function components)
â React.lazy (code splitting powered by Suspense)
â .contextType in class componentshttps://t.co/LJx7ItF4wYâ React (@reactjs) October 24, 2018
When apps start to grow you can easily end up including too many components making it heavier and slow to load. One of the solutions to this problem is Code-Splitting and Webpack is probably the most popular tool in the React ecosystem to perform the task of bundling and generating files that can be dynamically loaded at runtime. So if you ever wondered why we use so many import statements in our React apps, thatâs the reason.
Code-Splitting combined with lazy loading can help improve not only the performance of your app but the user experience by loading only the Components that really needed instead of loading everything during the initial load.
How Can I Implement React.lazy and Suspense
It’s actually not that hard. Letâs see a simple React âappâ as an example. I modified the default code generated by the create-react-app tool and included a new component called Cat.js.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | import React, {Component} from 'react'; class Cat extends Component { render() { return ( <div className="cat"> <img alt="Cat" src="http://placekitten.com/g/200/300" /> </div> ); } } export default Cat; |
The Cat.js component consist of just an image tag that shows a kitten from placekitten.com.
In the App.js file I import the Cat.js component and I added a button to show and I hide the kitten image as shown here:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | import React, {Component} from 'react'; import './App.css'; import './Cat'; class App extends Component { constructor(props) { super(props); this.state = {showImage: false}; } showImage = () => { this.setState({showImage: true}); }; hideImage = () => { this.setState({showImage: false}); }; render() { if (!this.state.showImage) { return ( <div className="App"> <header className="App-header"> <button onClick={this.showImage}> Show </button> </header> </div> ); } else { return ( <div className="App"> <header className="App-header"> <Cat /> <button onClick={this.hideImage}> Hide</button> </header> </div> ); } } } export default App; |
To show and hide the image I conditionally render the Cat.js Component based on a state variable called âshowImageâ, so if the âshowImageâ variable is set to true, then the Cat.js Component is rendered if not is hidden. And by default it will be hidden. This is what is shown in the browser when “showImage” is set to true:

To implement React.lazy and Suspense I need change the import of the Cat.js Component, and it will look like this:
1 2 3 4 5 | const Cat = lazy(() => import('./Cat')); |
Also I need to wrap up the Cat Component in a Suspense tag like this:
1 2 3 4 5 6 7 | <Suspense fallback={<div>Loading...</div>}> <Cat /> </Suspense> |
Notice there’s a fallback prop, that’s used to give feedback to the user when the Component is loading and it could be just a message like “Loading…” or it could it a another Component showing a loading spinner for example.
And here’s how the App.js Component will look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | import React, {Component, Suspense, lazy} from 'react'; import './App.css'; const Cat = lazy(() => import('./Cat')); class App extends Component { constructor(props) { super(props); this.state = {showImage: false}; } showImage = () => { this.setState({showImage: true}); }; hideImage = () => { this.setState({showImage: false}); }; render() { if (!this.state.showImage) { return ( <div className="App"> <header className="App-header"> <button onClick={this.showImage}> Show </button> </header> </div> ); } else { return ( <div className="App"> <header className="App-header"> <Suspense fallback={<div>Loading...</div>}> <Cat /> </Suspense> <button onClick={this.hideImage}> Hide</button> </header> </div> ); } } } export default App; |
Now if you open Chrome dev tools (or any dev tool depending on your browser) you should see a GET request when you click on the button to show the image:

That “0.chunk.js” file at the bottom includes the Cat.js Component.
And that’s all you have to do. Obviously this is a simple example, but this same implementation can be used in other interesting places, for example in routing.
You can find this code here: https://github.com/gigo6000/react-suspense-lazy-example .
And the video version of this example is here:
Why use React.lazy and Suspense instead of React Loadable?
I think this is the question most React Loadable users are asking right now and the answer is pretty simple, because itâs a native solution. This happens every time a technology integrates something done by a third-party tool, in this case one of the most important reasons to switch is that you will have less dependencies in your project and that also means less things to load in your app, so there’s a performance benefit if you switch. Less is more, they say.
But something important to consider before switching is that React.lazy and Suspense are not yet available for server-side rendering, so if you do code-splitting in a server rendered app, you should better keep using React Loadable.
Warning
Important: Suspense at the moment is meant to be used for code splitting not for data fetching or caching yet.
Note: Suspense in 16.6 is meant to be used for code splitting. The data fetching part isnât ready yet! Donât use any âcacheâ package until we document and release it as stable. đ Unless youâre just experimenting.
â Dan Abramov (@dan_abramov) October 25, 2018