Next.js 13 and React Suspense: Create a loading component
Tags: nextjs, react, webdev
Published: 2023-05-31 14:29:20

**Written by [Suraj Vishwakarma](https://blog.logrocket.com/author/suraj-vishwakarma/)✏️**

It has been some time since [Next.js 13 was launched](https://nextjs.org/blog/next-13) in October 2022\. In the beta, we learned of some major changes coming to Next.js, like support for [Suspense](https://beta.reactjs.org/reference/react/Suspense), a React feature that lets you delay displaying a component until the children have finished loading. 

Loading screens are a crucial part of any website; by letting the user know that some processing is happening, you can reduce their frustration and decrease their chance of leaving the website. Additionally, by allowing content to load asynchronously, you can improve a website’s UX and performance. In this tutorial, we’ll learn how to create a loading component using Next.js 13 and React Suspense. Let’s get started! 

_Jump ahead:_

*   [What is React Suspense?](#what-is-react-suspense)
*   [Using Next.js 13 and React Suspense](#using-next-js-react-suspense)
*   [Setting up our Next.js 13 project](#setting-up-next-js-13-project)
    *   [Installing Next.js 13](#installing-next-js-13)
    *   [Removing unnecessary files and folders](#removing-unnecessary-files-folders)
    *   [Create a `loading.js` file](#create-loading-js-file)
*   [Creating the `movies` route](#creating-movies-route)

## What is React Suspense?

[React’s Suspense component](https://blog.logrocket.com/react-suspense-data-fetching/#what-is-react-suspense) was first added to React in v16.6, which was released in 2018\. Suspense handles asynchronous operations like code splitting and data fetching. In simple terms, it lets you display a fallback component until the child component is fully loaded. The code below shows React Suspense's syntax:

```javascript
<Suspense fallback={<Loading />}>
  <SomeComponent />
</Suspense>
```

To load multiple components, you can add multiple child components within the `<Suspense>` component. Suspense improves a website’s performance and user experience, becoming an important part of the React ecosystem. Now, Next.js offers a new way to add Suspense to an application using its [`app` directory, released as part of Next.js 13](https://blog.logrocket.com/next-js-13-app-directory/).

## Using Next.js and React Suspense <a name="using-next-js-react-suspense">

The Next.js `app` directory has introduced a new file convention; you can now add all the files and components related to the route in a single directory. This includes both components and CSS files, so there is no need to create a separate directory for CSS files. In the `route` directory, you can include the `loading.js` file to add your loading UI for React Suspense’s fallback component: ![Next Js React Suspense Loading JS File](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-react-suspense-loading-js-file.png)

Next.js supports server-side rendering, so the UI will take some time to load. In such cases, you can use Suspense to load the UI. The component in `loading.js` is defined as a functional component that can be exported as the default. The syntax is below:

```javascript
export default function Loading() {
  // You can add any UI inside Loading, including a Skeleton.
  return <LoadingSkeleton />
}
```

Now, let’s implement Suspense by building a small project in Next.js 13.

## Setting up our Next.js 13 project <a name="setting-up-next-js-13-project">

We’ll build a web application that uses the [TMDB API](https://developers.themoviedb.org/3) to fetch trending movies. We have two routes:

1.  `root(/)`: Displays a welcome screen in the application
2.  `movies(/movies)`: Displays the trending movies fetched from the API

### Installing Next.js 13 <a name="installing-next-js-13">

You can install Next.js 13 with the command below. Keep in mind that you'll need to have [Node.js](https://nodejs.org/en) pre-installed on your machine:

```bash
npx create-next-app@latest --experimental-app
```

Entering the command above in the terminal will prompt you to answer the following questions:

*   `What is your project named?`: Name your project whatever you want
*   `Would you like to use TypeScript with this project?`: No. If you wish, then you can continue with TypeScript, but there won’t be many changes
*   `Would you like to use ESLint with this project?`: Yes; [ESLint will be helpful in debugging errors](https://blog.logrocket.com/troubleshooting-next-js-app-eslint/#setting-up-eslint-next-js)
*   `Would you like to use src/ directory with this project?`: No, we’ll use the latest `app` directory

With that, the project will be automatically set up for you with the necessary packages installed.

### Removing unnecessary files and folders <a name="removing-unnecessary-files-folders">

There isn’t a lot of boilerplate code in Next.js, but we should clean it up anyways. Open the `app` directory and remove the `API` directory, which is for the server. Remove all the CSS code from the `global.css` file in the `app` directory. Now, open `page.js` and remove all the code within the `return` section. Then, enter the following code in `page.js` to display a basic page with a welcome message for the user:

```javascript
async function Page() {
  return (
    <div>
      <h3>List of trending Movies & TV</h3>
    </div>
  );
}
export default Page;
```

Now, let’s look at the layout section from the `layout.js` file:

```javascript
import { Suspense } from "react";
import Link from "next/link";
import Loading from "./loading";
export const metadata = {
  title: "Create Next App",
  description: "Generated by create next app",
};
export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        <h1>Trending Movies & Movies</h1>
        <li>
          <Link href="/">Home</Link>
        </li>
        <li>
          <Link href="/movies">Movie</Link>
        </li>
        <Suspense fallback={<Loading />}>{children}</Suspense>
      </body>
    </html>
  );
}
```

In the code above, we created a `navbar` in the body section that will be displayed across all the routes. In `navbar`, we have links to `root`, `movies`, and `TV` routes.

### Create a `loading.js` file <a name="create-loading-js-file">

In the `root` directory, create the `loading.js` file with the code below:

```javascript
export default function Loading() {
  return <p>Loading Data...</p>;
}
```

We’ve created a basic loading component for display, but you can add a much [more sophisticated loading screen, like spinners](https://blog.logrocket.com/spinners-notifications-react-app/#adding-modern-spinners-react-spinners) or a [skeleton loading screen](https://blog.logrocket.com/build-skeleton-screen-css/). The functional component and file naming convention will remain the same.

## Creating the `movies` route <a name="creating-movies-route">

In Next.js 13, creating a route is similar to its previous versions. Create a directory within the app directory named `movies`. Inside `movies`, create a file named `page.js` with the code below:

```javascript
async function getMovies() {
  let res = await fetch(
    `https://api.themoviedb.org/3/trending/movie/day?api_key=${process.env.NEXT_PUBLIC_TMDB_API}`
  );
  await new Promise((resolve) => setTimeout(resolve, 2000));
  return res.json();
}

async function Trending() {
  let { results } = await getMovies();
  return (
    <div>
      <h3>Movies</h3>
      {results &&
        results.map((index) => {
          return <li>{index.title}</li>;
        })}
    </div>
  );
}
export default Trending;
```

Above, we have a two-component file. `getMovies()` fetches data from the API, which is sent to the default functional component with the name `Trending`. You can see that this is a server-side rendering component. It has an async functional component for promise-based data fetching because Suspense will know that data fetching is happening. We've also implemented a delay of two seconds to see the loading component properly. 

In the `Trending` component, we call the `getMovies()` function to get the fetched data. In the return, we are mapping the data to display all the trending movies in a list. 

You might find it unusual that we haven’t used Suspense yet. Next.js 13 understands when there is something loading; if there is a `loading.js` file in the `route` or even the `root` directory, it will display its loading component when loading occurs. 

We can add different loading components separately in every route with the addition of the `loading.js` file. Let’s check out the following gif displaying the output: ![Next js React Suspense Loading JS File](http://blog.logrocket.com/wp-content/uploads/2023/05/next-js-react-suspense-loading-js-file.gif) 

Optionally, you can also create boundaries with Supsense. Using these, if any component isn't fully loaded, then the loading component will be displayed. For better performance, this `<Suspense>` component can be in the layout and page components.

## Conclusion

Building a loading component with Next.js 13 and React Suspense can significantly improve the user experience of your web application. With Suspense, you can easily create loading states for data-fetching and dynamic imports, making your application more responsive and efficient. 

By following the steps outlined in this article, you can create a smooth loading experience for your users, reducing frustration and improving engagement. Whether you're building a simple website or a complex application, using Next.js 13 and React Suspense can help you create a more seamless and enjoyable user experience. 

Keep in mind that Next.js 13 is in beta at the time of writing, so you might occasionally experience some unusual behavior. I hope this article has helped you understand Suspense in Next.js 13. Thanks for reading!

---

##[LogRocket](https://lp.logrocket.com/blg/react-signup-general): Full visibility into your production React apps

Debugging React applications can be difficult, especially when users experience issues that are hard to reproduce. If you’re interested in monitoring and tracking Redux state, automatically surfacing JavaScript errors, and tracking slow network requests and component load time, [try LogRocket](https://lp.logrocket.com/blg/react-signup-general).

[![LogRocket Signup](https://blog.logrocket.com/wp-content/uploads/2017/03/1d0cd-1s_rmyo6nbrasp-xtvbaxfg.png)](https://lp.logrocket.com/blg/react-signup-general)

[LogRocket](https://lp.logrocket.com/blg/react-signup-general) combines session replay, product analytics, and error tracking – empowering software teams to create the ideal web and mobile product experience. What does that mean for you?

Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay problems as if they happened in your own browser to quickly understand what went wrong.

No more noisy alerting. Smart error tracking lets you triage and categorize issues, then learns from this. Get notified of impactful user issues, not false positives. Less alerts, way more useful signal.

The LogRocket Redux middleware package adds an extra layer of visibility into your user sessions. LogRocket logs all actions and state from your Redux stores.

Modernize how you debug your React apps — [start monitoring for free](https://lp.logrocket.com/blg/react-signup-general).