Suraj Vishwakarma I am an enthusiastic programmer who loves to write code and blog posts so that others can understand technology.

Next.js 13 and React Suspense: Create a loading component

4 min read 1381 104

React Suspense Next JS

It has been some time since Next.js 13 was launched in October 2022. In the beta, we learned of some major changes coming to Next.js, like support for 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?

React’s Suspense component 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:

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

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.

Using Next.js and 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
Image obtained from the official Next.js beta docs

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:

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

We’ll build a web application that uses the TMDB API 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

You can install Next.js 13 with the command below. Keep in mind that you’ll need to have Node.js pre-installed on your machine:

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
  • 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

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:

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

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

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">
        <h1>Trending Movies & Movies</h1>
          <Link href="/">Home</Link>
          <Link href="/movies">Movie</Link>
        <Suspense fallback={<Loading />}>{children}</Suspense>

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

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

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 or a skeleton loading screen. The functional component and file naming convention will remain the same.

Creating the 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:

async function getMovies() {
  let res = await fetch(
  await new Promise((resolve) => setTimeout(resolve, 2000));
  return res.json();

async function Trending() {
  let { results } = await getMovies();
  return (
      {results && => {
          return <li>{index.title}</li>;
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

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.


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!

Get set up with LogRocket's modern React error tracking in minutes:

  1. Visit to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.
  3. $ npm i --save logrocket 

    // Code:

    import LogRocket from 'logrocket';
    Add to your HTML:

    <script src=""></script>
    <script>window.LogRocket && window.LogRocket.init('app/id');</script>
  4. (Optional) Install plugins for deeper integrations with your stack:
    • Redux middleware
    • ngrx middleware
    • Vuex plugin
Get started now
Suraj Vishwakarma I am an enthusiastic programmer who loves to write code and blog posts so that others can understand technology.

Leave a Reply