Overview
You may have come across the term- “lazy loading in React”, but most of you won’t be familiar with exactly what is lazy loading in React. Lazy loading is not a new concept. It has been available for quite some time. In essence, lazy loading means that a component or a part of code must get loaded when it is required. It is also referred to as code splitting and data fetching. Now, the next question is, how to do lazy loading in react?
Talking about React specifically, it bundles the complete code and deploys all of it at the same time. Now, usually, that's not a bad idea, since React SPAs (Single page application) are quite small and do not affect the performance. But what if we have a gigantic application, like a content management system with a customer portal, admin portal etc. In such a case, it does not seem like a smart idea to load the complete application.
- It will be a huge application and will cost a lot of unnecessary data transfer which can lead to slow loading of the website.
- A customer login, will not have access to admin specific features, so loading it is a waste of memory and time.
In this post, I will try to explain the advantages of lazy loading in react and how to implement it in React.
Advantages
In situations where we know that certain code/features will not be accessible to all the users or the user does not access it frequently, it is best to load them when the user requests for it. This improves user experience as well as initial loading time.
For example, let's consider that our application has two sections, A and B. Size of A is 1 MB and its loading time is approximately 1 second. Size of B is also 1 MB and so its loading time is also 1 second. And we know that a user will access either of the sections, or a user accessing section A will rarely access section B and vice versa. If we were to load the complete application at the starting of our application, it would cost the user 2 MB of data and the loading time will also be 2 seconds. The user might not like to wait for 2 seconds or won't be happy that a site is costing them a lot of data. This can be improved and halved with proper lazy loading through lazy load react components.
Note: This is not the general case. Small single-page applications are usually in kbs.
Prerequisites
To follow this tutorial, you’ll need the following:
-
Latest Node version installed
-
create-react-apptool1npm install -g create-react-app
General instructions
-
We will perform lazy loading in React with react suspense and without it.
-
First of all, create the app using
npm create-react-app1npm create-react-app my-app -
Now run the app by running following command in the project directory root
1npm start -
The default react app will run in
http://localhost:3000 -
Let the directory structure be
1| 2|-src 3| |-components 4| | |-Admin.js 5| | |-Customer.js 6| | |-Home.js 7| |-app.js 8|-index.js -
Application will first render
app.jswhich will have an input field. We will pass the input received as props to Home, and renderHome.js. Based on props received, we will either renderAdminorCustomer.
Using React Suspense (React 16.6+)
From React 16.6+, react added React Suspense which performs lazy loading.
- In our
Home.js, we will lazy load Admin and Customer1import React, { Suspense } from "react"; 2const Customer = React.lazy(() => import("./Customer.js")); 3const Admin = React.lazy(() => import("./Admin.js")); 4//Instead of regular import statements, we will use the above approach for lazy loading 5export default (props) => { 6if (props.user === "admin") { 7return ( 8// fallback component is rendered until our main component is loaded 9<Suspense fallback={<div>Loading</div>}> 10<Admin /> 11</Suspense> 12); 13} else if (props.user === "customer") { 14return ( 15<Suspense fallback={<div>Loading</div>}> 16<Customer /> 17</Suspense> 18); 19} else { 20return <div> Invalid User </div>; 21} 22};
Without React Suspense
When talking about react lazy loading, if you are working with React version prior to 16.6, you won't have the Suspense component. It is best to upgrade to the latest version and use Suspense. If you're not able to upgrade and still want this feature, it is still possible to create your own React Suspense component. I will be using Higher Order Component(HOC).
- Our HOC (
lazyLoader.js)1const lazyLoader = (importComp) => { 2 return class extends React.Component { 3 state: { 4 component: null; //initializing state 5 }; 6 //loading the component and setting it to state 7 componentDidMount() { 8 importComp().then((comp) => setState({ component: comp.default })); 9 } 10 11 //rendering the component 12 render() { 13 const C = this.state.component; 14 return C ? <C {...this.props} /> : null; 15 } 16}; 17 18};
export default lazyLoader; ```
-
Our calling component, in this case
Home.js1import React from "react"; 2import { lazyLoader } from "./lazyLoader"; 3const Customer = lazyLoader(() => import("./Customer.js")); 4const Admin = lazyLoader(() => import("./Admin.js")); 5//Instead of regular import statements, we will use the above approach for lazy loading 6export default (props) => { 7if (props.user === "admin") { 8return <Admin />; 9} else if (props.user === "customer") { 10return <Customer />; 11} else { 12return <div> Invalid User </div>; 13} 14};This was all about how to implement lazy loading in react, if you need the fallback feature, you can update HOC's render method where it is returning null. Instead of null, you can return your fallback component, and it can be passed as props too.
Now our HOC would look like -
1const lazyLoader = (importComp, fallback) => { 2 return class extends React.Component { 3 state = { 4 component: null, //initializing state 5 }; 6 //loading the component and setting it to state 7 componentDidMount() { 8 importComp().then((comp) => setState({ component: comp.default })); 9 } 10 11 //rendering the component 12 render() { 13 const C = this.state.component; 14 return C ? ( 15 <C {...this.props} /> 16 ) : fallback ? ( 17 fallback 18 ) : ( 19 <div>loading</div> 20 ); 21 // If component is not loaded then return fallback component, if fallback is not provided then use default loading 22 } 23}; 24 25}; 26export default lazyLoader;

