Using Suspense for Code Splitting

Loading

In React, Suspense is a built-in component that helps in handling asynchronous loading states for components that are dynamically imported. When combined with React.lazy(), it allows you to load components lazily, which means loading them only when they are needed, rather than loading them upfront. This can significantly improve the performance of your app by reducing the initial bundle size.

Steps to Use Suspense for Code Splitting:

1. Install React (if you haven’t already)

Make sure you’re using a React project. If you need a new React project, you can create one with Create React App:

npx create-react-app my-app
cd my-app
npm start

2. Import React.lazy and Suspense

To use code splitting, you need to import both React.lazy and Suspense from React.

import React, { lazy, Suspense } from 'react';

3. Lazy Load Components with React.lazy()

Use React.lazy() to dynamically import your components. For example, if you have a Home component that you want to load lazily, you would do something like this:

const Home = lazy(() => import('./Home'));

React.lazy() takes a function that returns a dynamic import() statement. This tells Webpack to split this component into a separate chunk.

4. Wrap Components with Suspense

Suspense is a component that you wrap around your lazy-loaded components to provide a loading fallback (such as a loading spinner or message) while the component is being loaded.

function App() {
  return (
    <div>
      <h1>Welcome to my React app!</h1>
      <Suspense fallback={<div>Loading...</div>}>
        <Home />
      </Suspense>
    </div>
  );
}
  • The fallback prop of Suspense specifies the UI to show while the component is loading. In this example, a simple loading message (<div>Loading...</div>) is shown until Home is fully loaded.

5. Example with Multiple Lazy Loaded Components

You can use Suspense to load multiple components lazily:

import React, { lazy, Suspense } from 'react';

const Home = lazy(() => import('./Home'));
const About = lazy(() => import('./About'));

function App() {
  return (
    <div>
      <h1>React Lazy Loading with Suspense</h1>
      <Suspense fallback={<div>Loading Home...</div>}>
        <Home />
      </Suspense>
      <Suspense fallback={<div>Loading About...</div>}>
        <About />
      </Suspense>
    </div>
  );
}

export default App;

In this example:

  • The Home component is lazily loaded, and while it’s loading, the text “Loading Home…” is shown.
  • Similarly, the About component is lazily loaded, and while it’s loading, the text “Loading About…” is shown.

6. React Router with Code Splitting

If you are using React Router, you can combine lazy loading with Suspense to load routes on demand.

import React, { lazy, Suspense } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

const Home = lazy(() => import('./pages/Home'));
const About = lazy(() => import('./pages/About'));

function App() {
  return (
    <Router>
      <Suspense fallback={<div>Loading...</div>}>
        <Switch>
          <Route path="/" exact component={Home} />
          <Route path="/about" component={About} />
        </Switch>
      </Suspense>
    </Router>
  );
}

export default App;

In this case:

  • The Home and About components are loaded lazily when the user navigates to those routes.
  • The Suspense component wraps the entire route switch, so any lazily-loaded component will show the fallback content until it’s loaded.

7. Using Suspense with Custom Fallbacks

You can provide a custom fallback UI. For example, you might want to show a spinner or a progress bar while the component is loading:

import React, { lazy, Suspense } from 'react';
import { CircularProgress } from '@material-ui/core';

const Home = lazy(() => import('./Home'));

function App() {
  return (
    <div>
      <h1>Lazy Loading with Suspense</h1>
      <Suspense fallback={<CircularProgress />}>
        <Home />
      </Suspense>
    </div>
  );
}

export default App;

Here, we’re using Material-UI’s CircularProgress component to show a spinner while the Home component is being loaded.

8. Error Boundaries with Suspense

While Suspense handles loading states, it doesn’t catch errors that occur during the loading of components. To handle errors, you can use Error Boundaries in combination with Suspense.

import React, { Component, lazy, Suspense } from 'react';

// Error Boundary
class ErrorBoundary extends Component {
  state = { hasError: false };

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

  componentDidCatch(error, info) {
    console.log("Error occurred:", error, info);
  }

  render() {
    if (this.state.hasError) {
      return <div>Something went wrong!</div>;
    }
    return this.props.children;
  }
}

const Home = lazy(() => import('./Home'));

function App() {
  return (
    <div>
      <h1>React Suspense with Error Boundaries</h1>
      <ErrorBoundary>
        <Suspense fallback={<div>Loading...</div>}>
          <Home />
        </Suspense>
      </ErrorBoundary>
    </div>
  );
}

export default App;

Here, if there’s an error in loading the Home component, the ErrorBoundary will catch the error and display an error message.

9. Benefits of Using Suspense for Code Splitting

  • Improved Performance: Code-splitting with Suspense ensures that only the necessary parts of your app are loaded initially, making your app load faster.
  • Reduced Initial Bundle Size: With lazy loading, large components are split into smaller chunks, reducing the initial JavaScript payload.
  • User Experience: By showing a fallback UI while waiting for a component to load, you can provide a smoother experience to your users, rather than them seeing a blank screen.

Leave a Reply

Your email address will not be published. Required fields are marked *