In this post we'll see how to lazy load routes in React.
Lazy load brings better performance as components are loaded on demand. During initial render only the required components are loaded so the initial bundle size is small.
When components are loaded lazily as separate chunks that results in splitting of code in separate bundles.
How to implement lazy loading for routes in React Router
React Router version used here is version 7.
Two things that are needed for implementing lazy loading for routes in React
- Using React.lazy function
- Using React.Suspense built-in component
Using React.lazy
Using lazy function, you can defer loading components code until it is rendered for the first time. The parameter in the React.lazy function is a function that returns a Promise. This function (which is passed as a parameter) will not be called until the first time you attempt to render the returned component. Note that, both the returned Promise and the Promise's resolved value will be cached, so React will not call this function more than once.
For lazy load routes, wrap the import statement for the components that are mapped to the route, with in the lazy function. With this the component will be loaded only when the route is visited.
const Home = lazy(() => import('./components/routes/home')); const About = lazy(() => import('./components/routes/about'));
Using React.Suspense
While the lazily loaded component is getting loaded you may want to show some fallback UI in place of the actual UI that can be done using the Suspense component.
With Suspense you can use following props-
- children- Actual component that is wrapped with in Suspense.
- fallback- UI which is rendered while the actual UI is getting loaded. Suspense will automatically switch to fallback when children suspends, and back to children when the data is ready.
With React Router version 7 it is better to use Suspense with each route definition.
<Route index element={<Suspense fallback={<>Loading....</>}><Home /></Suspense>} /> <Route path="about" element={<Suspense fallback={<div>Loading....</div>}><About /></Suspense>
Lazy load routes React example
Components
As stated above there are Home and About components.
src\components\routes\Home.js
const Home = () => { return ( <> <h2>This is home page</h2> </> ) } export default Home;
src\components\routes\About.js
const About = () => { return ( <> <h2>This is about page</h2> </> ); } export default About;
There is also a navigation menu component.
src\components\routes\NavigationNavLink.js
import { NavLink, Outlet } from "react-router"; import "./navigation.css"; const NavigationNavLink = () => { const style = (({ isActive, isPending }) => isPending ? "pending" : isActive ? "active" : "" ); return( <> <nav id="menu" className="navbar navbar-expand-lg bg-dark navbar-dark"> <div className="container-fluid"> <button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMenu" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation"> <span className="navbar-toggler-icon"></span> </button> <div className="collapse navbar-collapse" id="navbarMenu"> <ul className="navbar-nav"> <li> <NavLink className={style} to="/"> Home </NavLink> </li> <li> <NavLink className={style} to="/about"> About </NavLink> </li> </ul> </div> </div> </nav> <div className="container row mt-2"> <Outlet /> </div> </> ); } export default NavigationNavLink;
CSS
Uses CSS for active menu hightlight.
src\components\routes\navigation.css
#menu a:link, #menu a:visited { color: gray; } #menu a:hover { color: white; } #menu a.active { color: #7FFFD4; } #menu a { text-decoration: none; } #menu ul { gap: 1rem; }
Route Configuration
import { BrowserRouter, Route, RouterProvider, Routes } from 'react-router'; import NavigationNavLink from './components/routes/NavigationNavLink'; import { Suspense, lazy } from 'react'; const Home = lazy(() => simulateDelay(import('./components/routes/Home'))); const About = lazy(() => import('./components/routes/About')); function App() { return ( <> <BrowserRouter > <Routes> <Route path="/" element={<NavigationNavLink />}> <Route index element={<Suspense fallback={<>Loading....</>}><Home /></Suspense>} /> <Route path="about" element={<Suspense fallback={<div>Loading....</div>}><About /></Suspense>} /> </Route> </Routes> </BrowserRouter> </> ); } function simulateDelay(promise) { return new Promise(resolve => { setTimeout(resolve, 1000); }).then(() => promise); } export default App;
Since Home component doesn't have much data so a function is used to simulate delay of 1 second to see the fallback.
You can also see that components are loaded as separate chunks.
That's all for this topic Lazy Loading Routes in React. If you have any doubt or any suggestions to make please drop a comment. Thanks!
Related Topics
You may also like-
No comments:
Post a Comment