Phase 4 - Improving User Experience using React.lazy
Tags: react, codingbootcamp, loadingpage, javascript
Published: 2023-02-09 14:34:36

Although a 'visually appeasing' frontend application is not really a requirement for most of our coding bootcamp projects, as a creative, I just can't help myself sometimes. Even as a junior engineer, I believe the overall user experience is important. 

For my recent project, [**Buckit**](https://github.com/breonwhite/phase-4-project-buckit), a bucket list management app, I wanted to step it up a little by adding some background images to the app. I'm no css expert, but I found a hacky way to add background images using [MUI](https://mui.com/):

```
import Box from '@mui/material/Box';
import sky1 from '../images/sky1.jpg';

<Box
      style={{
      backgroundImage: `url(${sky1})`,
      backgroundSize: "cover",
      height: "100vh",
      ....
    }}>
```

![signup/page](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/8zg6cj2przgjyxp5u3s3.png)

## Looking good, but moving slow
Unfortunately, immediately after adding the images, the performance of the site was _very_ noticeable. Directing between pages would take a few seconds to load the background and since this project was using [Rails authentication](https://guides.rubyonrails.org/security.html) between routes, I figured my application just needed a few more seconds to think. 

## Creating a (DRY) Loading Page  
Since adding these background images were just a '_nice to have_' and a bit out of scope, I didn't want to go down a rabbit hole trying to make the site overly efficient --(we can come back and do that later). However, the question still remained --how can I create a simple loading page while keeping my code clean? 

That's when I discovered `React.lazy`. 

> _The React.lazy function lets you render a dynamic import as a regular component..._

After reading [react's documentation](https://reactjs.org/docs/code-splitting.html#reactlazy), I got to work on my application!

## Refactoring my App.js file
I started by importing `Suspense` from React in my `App.js` file:

```
import React, { Suspense } from 'react';
```
Next, I removed my importing components and assigned them to variables instead using the `React.lazy` feature.

**Before:**
```
import React, { Suspense } from 'react';
import Home from './containers/Home';
import Item from './containers/item/Item';
import Items from './containers/item/Items';

function App() { ... 
```
**After:**
```
import React, { Suspense } from 'react';

function App() {
  const Home = React.lazy(() => import('./containers/Home'));
  const Item = React.lazy(() => import('./containers/item/Item'));
  const Items = React.lazy(() => import('./containers/item/Items'));
....
```

Lastly, I wrapped everything in the `Div` in the `Suspense` component imported from React. 

```
function App() {

  const Home = React.lazy(() => import('./containers/Home'));
  const Item = React.lazy(() => import('./containers/item/Item'));
  const Items = React.lazy(() => import('./containers/item/Items'));
  
  return (
    <div className="App">
      <Suspense fallback={<div>Loading...</div>}> 
      <UserProvider>
      <Navbar />
        <Routes>
          ...
      </Suspense>
    </div>
```

> For now, I just went with a 'Loading...' placeholder as the fallback --but it's cool to know that you can design a custom loading page in the future if you want

& that's it! SO EASY. A few line changes in ONE file. No refactoring my `Routes`, no impacts on my `context` or the rest of my application. 

Now, when the page is loading you'll see the small 'Loading...' text for a split second. Thanks React!