DEV Community

Abhay Singh Kathayat
Abhay Singh Kathayat

Posted on

Improve React App Performance with Lazy Loading Components

Lazy Loading Components in React

Lazy Loading is a technique in React that allows you to load components only when they are needed. This helps improve the performance of your application by reducing the initial load time, as only the required parts of the app are loaded at first, and the rest is loaded dynamically when necessary.

React provides the React.lazy function and the Suspense component to implement lazy loading.


How Lazy Loading Works

  1. React.lazy: Dynamically imports a component.
  2. Suspense: Displays a fallback (e.g., a loading spinner) while the component is being loaded.

Syntax

const LazyComponent = React.lazy(() => import('./path/to/Component'));

function App() {
  return (
    <React.Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </React.Suspense>
  );
}
Enter fullscreen mode Exit fullscreen mode
  • React.lazy: Dynamically imports the specified component.
  • Suspense: Wraps the lazy-loaded component and provides a fallback UI while the component is loading.

Example 1: Basic Lazy Loading

Without Lazy Loading

import React from "react";
import HeavyComponent from "./HeavyComponent";

function App() {
  return (
    <div>
      <h1>App Component</h1>
      <HeavyComponent />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

In this example, the HeavyComponent is always loaded, even if it’s not immediately needed, increasing the initial load time.

With Lazy Loading

import React, { Suspense } from "react";

const HeavyComponent = React.lazy(() => import("./HeavyComponent"));

function App() {
  return (
    <div>
      <h1>App Component</h1>
      <Suspense fallback={<div>Loading Heavy Component...</div>}>
        <HeavyComponent />
      </Suspense>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Now, HeavyComponent is loaded only when it is rendered. The fallback UI (e.g., "Loading Heavy Component...") is displayed while the component is being fetched.


Example 2: Lazy Loading with React Router

Lazy loading is especially useful in routing to load components for specific routes only when those routes are accessed.

import React, { Suspense } from "react";
import { BrowserRouter as Router, Routes, Route } from "react-router-dom";

const Home = React.lazy(() => import("./Home"));
const About = React.lazy(() => import("./About"));
const Contact = React.lazy(() => import("./Contact"));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading Page...</div>}>
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/about" element={<About />} />
          <Route path="/contact" element={<Contact />} />
        </Routes>
      </Suspense>
    </Router>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode
  • React.lazy: Lazily loads components for routes like /about and /contact.
  • Suspense: Displays the fallback UI while the components are being loaded.

Benefits of Lazy Loading

  1. Improved Performance: Reduces the initial load time by deferring the loading of unnecessary components.
  2. Better User Experience: Loads components dynamically, which helps in creating responsive apps.
  3. Reduced Bundle Size: Splits the code into smaller chunks, minimizing the size of the JavaScript bundle loaded initially.

Advanced Example: Lazy Loading Multiple Components

You can lazy-load multiple components and combine them with conditional rendering.

import React, { Suspense, useState } from "react";

const LazyComponent1 = React.lazy(() => import("./LazyComponent1"));
const LazyComponent2 = React.lazy(() => import("./LazyComponent2"));

function App() {
  const [showComponent1, setShowComponent1] = useState(false);
  const [showComponent2, setShowComponent2] = useState(false);

  return (
    <div>
      <button onClick={() => setShowComponent1(true)}>Load Component 1</button>
      <button onClick={() => setShowComponent2(true)}>Load Component 2</button>

      <Suspense fallback={<div>Loading Component...</div>}>
        {showComponent1 && <LazyComponent1 />}
        {showComponent2 && <LazyComponent2 />}
      </Suspense>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Error Handling with Lazy Loading

If the lazy-loaded component fails to load (e.g., network error), React does not provide built-in error handling for lazy loading. You can use ErrorBoundary to handle such scenarios.

import React, { Suspense } from "react";

const LazyComponent = React.lazy(() => import("./LazyComponent"));

class ErrorBoundary extends React.Component {
  constructor(props) {
    super(props);
    this.state = { hasError: false };
  }

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      return <div>Error loading component</div>;
    }
    return this.props.children;
  }
}

function App() {
  return (
    <ErrorBoundary>
      <Suspense fallback={<div>Loading...</div>}>
        <LazyComponent />
      </Suspense>
    </ErrorBoundary>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Best Practices for Lazy Loading

  1. Keep Fallbacks Simple: Use lightweight fallback UIs like spinners or text messages.
  2. Chunk Components Wisely: Split components logically, such as by route or by feature.
  3. Combine with Code Splitting: Use tools like Webpack or Vite for effective code splitting.

Conclusion

Lazy loading in React is a powerful way to improve application performance and optimize the user experience. By loading components dynamically using React.lazy and Suspense, you can reduce the initial load time and ensure that only the necessary parts of your application are fetched.


Top comments (0)