How to create a Preloader in Next.js
Tags: nextjs, react, css, beginners
Published: 2021-10-24 22:22:40

Before you read this article, I want you to know that it is a bit flawed, and I apologize for the mistakes I made previously, while authoring this article. 

I am super thankful for the people who shared their opinions in the comment, and I learned from all of them, a great deal! You can find a new article that shows how you can [add a preloader to a Next.js site, the right way, here](https://meje.dev/blog/building-a-nextjs-preloader-the-right-way)

There's always a need to have all the content of a webpage ready before it is displayed to whoever is visiting your web app/website.

In situations where the contents of the webpage aren't ready, people would have to wait for it to be displayed, and this causes a very high decline rate of people who visit your website.

In this article, we'll have a look at how we can build a loading screen component that is displayed whenever the contents of the page is about to be mounted onto the DOM.

Before you read this article any further, you should be familiar with:

- [React](https://reactjs.org/), a declarative JavaScript library for building user interfaces
- [Next.js](https://nextjs.org/), a framework of React, used for building production-ready applications
- [Conditional rendering](https://seven.hashnode.dev/two-very-simple-ways-to-render-ui-conditionally-in-react) in React
- Animations in CSS

## Getting started

In this article, we’ll be using NextJS to set up our app, you can use [create-react-app](https://create-react-app.dev) if you are not familiar with NextJS. 

Let us start by installing the dependencies that we need in this project. We’d start by creating a nextjs app. The command below gets the dependencies that we need in a  Nextjs app.

```bash
npx create-next-app [name-of-your-app]
```
    
We’ll make use of the `"styled-component"` library to style the loading screen component. Let’s get the dependency above by typing the command below into our terminal.

```bash
npm install --save styled-components
```

## The components in our Nextjs app

In this section, we are going to see the different files that make up the architecture of this project, and their respective functions below.

The `pages` directory is where all the routing of the app takes place. This is an out-of-the-box feature of Nextjs. It saves you the stress of hard hard-coding your independent routes.

- `pages/api`: the api directory enables you to have a backend for your nextjs app, inside the same codebase, instead of the common way of creating separate repositories for your REST or GraphQL APIs and deploying them on backend hosting platforms like Heroku, and so on.

- `pages/_app.js`: is where all our components get attached to the DOM. If you take a look at the component structure, you’ll see that all the components are passed as `pageProps` to the `Component` props too.

```jsx
function MyApp({ Component, pageProps }) {
  return (
    <React.Fragment>
      <Component {...pageProps} />
    </React.Fragment>
  );
}
    
export default MyApp;
```
It is like the `index.js` file in Create-React-App. The only difference here is that you are not hooking your app to the DOM node called “root”.

```javascript
 React.render(document.getElementById("root"), <App />)
```
- `index.js` is the default route in the pages folder. When you run the command below, it starts up a development server and the contents of `index.js` are rendered on the web page.

```bash
npm run dev
```
## Building the loading screen component

The previous sections walked you through the process of installing the dependencies that are needed for building the loading screen component and the functions of each file in a typical Nextjs app.

In this section, we'll go through the step-by-step process of building the component itself.

First, we'll be taking a look at the style of the loader. We are using the styled component library for this purpose.

The `Screen` styled-component serves as the parent container that wraps the loading animation. It uses a `fade` keyframe to ensure the transition of the screen is properly utilized.

```jsx
// loadingScreen.js
import styled from "styled-components";

const Screen = styled.div`
  position: relative;
  height: 100vh;
  width: 100%;
  opacity: 0;
  animation: fade 0.4s ease-in forwards;
  background: black;

  @keyframes fade {
    0% {
      opacity: 0.4;
    }
    50% {
      opacity: 0.8;
    }
    100% {
      opacity: 1;
    }
  }
`;
```

The snippet below shows the `Balls` styled component. It serves as a container for the child elements in it. The corresponding `divs` in the container are the balls that we'll be animating.

You'll notice that there are unique `className`s assigned to each `div` element in the container. This is for us to be able to set an `animation-delay` property on each ball so that the oscillating effect can be seen properly.

```jsx
import styled from "styled-components";

const Balls = styled.div`
  display: flex;
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);

  .ball {
    height: 20px;
    width: 20px;
    border-radius: 50%;
    background: #1b5299;
    margin: 0 6px 0 0;
    animation: oscillate 0.7s ease-in forwards infinite;
  }

  .one {
    animation-delay: 0.5s;
  }
  .two {
    animation-delay: 1s;
  }
  .three {
    animation-delay: 2s;
  }

  @keyframes oscillate {
    0% {
      transform: translateY(0);
    }
    50% {
      transform: translateY(20px);
    }
    100% {
      transform: translateY(0);
    }
  }
`;
```
If you're new to animations in CSS. You can check this [guide](https://seven.hashnode.dev/the-abc-of-css-animation) that explains the fundamentals.

Now that you have seen the styles of the components above. We'll go ahead to reference the styles in the `LoadingScreeen` component below.

```jsx
import React from "react"
import styled from "styled-components"

const Screen = styled.div``

const Balls = styled.div``

const LoadingScreen = () => {
  return (
    <Screen>
      <Balls>
        <div className="ball one"></div>
        <div className="ball two"></div>
        <div className="ball three"></div>
      </Balls>
    </Screen>
  );
};

export default LoadingScreen;
```
## Implementing the preloader functionality

We've seen the function of the loading screen styles and how the animation works behind the scene.

In this section, we'll be importing the component into `_app.js`. Take a look at it below.

```jsx
import LoadingScreen from "../src/components/LoadingScreen";

function MyApp({ Component, pageProps }) {
  const [loading, setLoading] = React.useState(false);

  React.useEffect(() => {
    setLoading(true);
  }, []);

  return (
    <>
      {!loading ? (
        <React.Fragment>
          <Component {...pageProps} />
        </React.Fragment>
      ) : (
        <LoadingScreen />
      )}
    </>
  );
}

export default MyApp
```
The snippet above shows how we've used conditional rendering to check the state of the loading component. We had to create a local state variable that holds the current state with the `useState` React hook.

```javascript
const [loading, setLoading] = React.useState(false)
```
The initial state of the loader is set to a boolean value, `false`.

The `useEffect` hook is a lifecycle method in React that is fired whenever there's a change in the DOM. It combines all the lifecycle methods that a typical class-based component will have.

```javascript
  React.useEffect(() => {
    setLoading(true);
  }, []);
```

By setting the initial "falsy" state of the loader to be `true` in the `useEffect` hook. We're telling the browser to display the loader. 

## Conclusion
Formerly, I made use of the `setTimeout()` function to display the loader for a significant amount of time before showing the content of the UI.

```javascript
React.useEffect(() =>{
 setTimeout(() => setLoading(true), 6000);
})
```
Little did I know that it was a bad practice. This practice has a lot of performance issues which in turn would result in providing a poor UX (user experience) for users visiting the web-app, as the content on the webpage could have been ready before the time that was stated in the `setTimeout` function.

Thankfully, [Martin Vandersteen](https://dev.to/vdsmartin) and [Stephen Scaff](https://dev.to/stephenscaff) did well by explaining to me. You can take a look at this [thread](https://dev.to/vdsmartin/comment/1j7ep) to understand their ideas.

Below is a GIF that shows what we've been building all along.

![preloader demo site](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/b42dd2hwzen23ycjl353.gif)

Although, this is an approach that helps us to have the content on a webpage/site available. If you are dealing with dynamic data, say from an API endpoint, the approach will be a little bit different.

You can decide to make use of this [react-spinners](https://www.npmjs.com/package/react-spinners) package if you don't want to spend time creating a custom loading component all by yourself.

Thank you for reading this article. Kindly leave your thoughts in the comments section, and share this article with your peers, Thanks.