Try   HackMD
tags: self-taught

Lazy loading in React 18

I. What is lazy loading

Lazy loading is a strategy to identify resources as non-blocking (non-critical) and load these only when needed. It's a way to shorten the length of the critical rendering path, which translates into reduced page load times.
Lazy loading can occur on different moments in the application, but it typically happens on some user interactions such as scrolling and navigation.

src: https://developer.mozilla.org/en-US/docs/Web/Performance/Lazy_loading

So basically, it's a practice of delaying load or initialization of resources or objects until they’re ready to be load or until users need them.
By this, we can improve performance and save system resources.

Ex: when you fetching data from API, it takes time, and we usually show a loading text or spiner to let users know data is loading.

II. Old method

What we used to do to display the loading sign while waiting for API to fetch is:

  • creating a loading state (false, initially)
  • then when we fetch API, loading state is updated to true
  • when the fetch is done, loading state was updated to false
  • we also have an if statement on render to output the loading sign when it's state is true, otherwise, render the fetched content
import './App.css'; import React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { solid } from '@fortawesome/fontawesome-svg-core/import.macro'; import BerlinTemp from "./WeatherTag"; import NYTemp from "./WeatherTag2"; import SFTemp from "./WeatherTag3"; function App() { return ( <div style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "center", padding: "40px 0" }} > <h2> <span>How's the temperature today ?</span> </h2> <BerlinTemp /> <NYTemp/> <SFTemp/> </div> ); } export default App;

What is painful about this is that, anywhere you want a loading sign, you'll need a state to control the loading status. So i have a loading state for each <BerlinTemp/>, <NYTemp/>, <SFTemp/> component.
It is not that big of a deal, but wouldn't it be nice if we don't have to to that.

III. With React 18

"Suspense" has been around for several versions as an experimental feature. React 18.0.0 was out on March 29, 2022 making it an official feature together with some other updates.

The above code will be re-write as below:

import './App.css'; import React from 'react'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { solid } from '@fortawesome/fontawesome-svg-core/import.macro'; const NYTemp = React.lazy(() => import ('./WeatherTag2')); const BerlinTemp = React.lazy(() => import ('./WeatherTag')); const SFTemp = React.lazy(() => import ('./WeatherTag3')); function App() { return ( <div style={{ width: "100%", display: "flex", flexDirection: "column", alignItems: "center", padding: "40px 0" }} > <h2> <span>How's the temperature today ?</span> </h2> <React.Suspense fallback={<FontAwesomeIcon icon={solid('rotate')} spin/>}> <BerlinTemp /> <NYTemp/> <SFTemp/> </React.Suspense> </div> ); } export default App;
  • We no longer need loading state in each component
  • Instead, wrap the components with Suspense which takes a required fallback props to display the loading sign when components are fetching data.
  • And, the components also need to be imported with lazy() to make it work.

==> We have the same result as the old method.

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Another interesting thing is that, we can add suspense inside a nother suspense, and it will delay the display of 2nd suspense until the first one was rendered.

... <React.Suspense fallback={<FontAwesomeIcon icon={solid('rotate')} spin/>}> <BerlinTemp /> {/* <NYTemp/> <SFTemp/> */} <React.Suspense fallback={<FontAwesomeIcon icon={solid('rotate')} spin/>}> <NYTemp/> <React.Suspense fallback={<FontAwesomeIcon icon={solid('rotate')} spin/>}> <SFTemp/> </React.Suspense> </React.Suspense> </React.Suspense> ...

> As you can see, <BerlinTemp/> component is loaded first, then <NYTemp/>, and finally <SFTemp/>

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

IV. Conclusion

If you're using React 18, give it a try.
I bet you'll like it.
See you again with another cool updates from React.