Implementing Layout Structure in NextJs the right way
Tags: nextjs, layouts, frontend, react
Published: 2022-07-04 10:16:38


![Layout Structure in NextJs](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/s9bh0b9hj8b3idmknfkn.jpeg)

## Intro & Why Layouts?
When I started coding in NextJs, I really struggled while implementing Layout based architecture. The React model allows us to deconstruct a page into a series of components. Many of these components are often reused between pages. For example, you might have the same Header and Footer on every page.

I read some articles and came to a proper solution for Layout based architecture in simple or complex NextJs applications.

### Tutorial Outcomes
At the end of the tutorial you will be able to;

- Create a global layout for NextJs pages

- Create multiple dedicated layouts for different type of pages like GlobalLayout, DashboardLayout.

- You will learn how to fix remount and **state persistence** issues while implementing layouts in **NextJs**.

---

## Setting up the NextJs project
Let's create a new NextJs project by running CNA(create-next-app) command with the default template, in the terminal(personally prefer Git Bash),

```
npx create-next-app <app-name>
# or
yarn create next-app
```
Navigate to project directory,

```
cd <app-name>
```
Run newly created NextJs app in a development environment,

```
npm run dev
// or
npm start
```
Now application should be running at `localhost:300`.

Lets look at the directories you will get after bootstraping NextJs application;

```
/<app-name>
   /pages
        /_app.js
        /index.js
   /public
   /styles
```

## Adding necessory components
Create another file inside the pages directory, named `about.js`, which will be mapped to `/about` as About page.

Create another directory inside the root directory as components;

Inside the Components directory create directories named, **Layout**, **Header**, and **Footer**, each with `index.js` file inside it.

The project directory should look like this;

```
/<app-name>
   /pages
      /_app.js
      /index.js
      /about.js
   /public
   /styles
   /components
      /Layout
          /index.js
      /Header
          /index.js
      /Footer
          /index.js
```

## Adding Content
Now open index.js inside the /pages directory, and clean up the mockup code initially created by running the `create-next-app` command. Add the following code instead;


![Homepage content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jzdwb58qqeiv8nbfliqg.png)

And inside the about.js page,

![About page content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ffdggje3fag15p84woc5.png)

## Implementing Layout
Now you can see, that Components like the Header, Footer are being shared between both the pages. We are going to separate these shared components inside the Layout component, so we do not need to import them in every single page.

Open the `index.js` file inside **Layout** directory and add this code;

![Layout component content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/97kyc9t8o5x37g0ty9es.png)

What are we doing here exactly? Nothing special. We are using the `children `prop provided by reacting, which will let us wrap pages inside Layout. Anything wrapped inside this Layout component will be added to react render tree between `<main>` tag at,

`<main>{children}</main>`

Now let's implement this layout inside our pages, and make the following changes to `index.js` and `about.js` inside pages directory;

![Homepage with Layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2ngz25wxr9bkislmpook.png)

and inside `/pages/about.js`,

![About page with Layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4khx65ja0oeyetddt6f3.png)

**Hurrah!** We got it. We have successfully implemented Layout architecture inside our NextJs app. But hold on, there is a major drawback to this implementation. Unnecessary **remounting** and **rerender** at every navigation 😒. Let me explain.

## Fixing the Remounting and Rerendering issue
First of all, let me demonstrate what I mean by unnecessary re-renders and remounting issues. Let's start a development server, by running

`npm run dev` or `npm start`

If you had followed me along, you must see this basic page when visiting `localhost:3000` in browser of your choice(unless its **Internet Explorer** 😉)

![Layout implementation output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cfacpz5z45lrdpvo8iiw.png)

Isn't it ugly, right? 😊, I guessed your answer. Let's give it a bit of shape with Tailwind CSS(really awesome, if you haven't tried it, you should give it a shot).

I have added some styles, and a useEffect hook to demonstrate to you, what is actually going on. Have a look;

![Header component useEffect listner](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4kssl13x7hkk75o9dte4.png)

The **`useEffect `**hook was provided in ReactJs after **v16.8**, which pretty much replaces the 3 life cycle methods (**`componentDidMount`**, **`componentWillUpdate`**, **`componentWillUnmout`**) of react class-based implementation.
Now our Header component should look like this;


![Header component content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bzhjgr0ng8izl8pnkeqh.png)

#### Testing Phase 1
Setup is done, now let's test this out. Open a terminal, and refresh your page. You must see in the terminal `Header mounted`;

![Layout implmentation Output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pumuyvyn1gm9hv3u8jhm.png)

Now it's time to navigate to the About page, by clicking About in the Header, you will see that header **first unmounts and then re-mounts again.**

![Layout implementation console output](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/raj9n2ii8gx2n9h1rosk.png)

Is this okay? You guessed it right. When navigating between pages, we want to **persist page state** (input values, scroll position, etc.) for a **Single-Page Application (SPA) experience**. But in our case, this is doing nothing, just separating the shared components, which is good but now what we want to achieve.

### Okay! Fix time
NextJs comes with the solution itself, by providing us with getLayout method. We need to refactor this code a bit, and we are good to go.

When using Next.js we often need to override the global App component to get access to some features like _persisting state_, or _global layouts_. This can be done by creating a file_app.js directly in the `/pages/` folder. If this file exists, then Next.js will use this instead of the default App.

Time to mess with _app.js file;

![_app.js content](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/huqtrm3vr1ot29jx9b8p.png)

What are we exactly doing here, we are telling NextJs to use Layout as specified at the page level, while preserving the memory(state, scroll position, etc.). When navigating between pages, we want to persist page state (input values, scroll position, etc.) for a Single-Page Application (SPA) experience.

This layout pattern enables state persistence because the React component tree is maintained between page transitions. With the component tree, React can understand which elements have changed to preserve the state.

### Refactoring Page Layouts
Let's refactor code inside pages, `index.js` and `about.js`.
Move the Layout from the component return state to `Component.getLayout` method like;


![Homepage content with Layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6u5wwpx6bqgsxkuc9fv8.png)

and for `/about.js` page;

![About page content with layout](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/4feoo4nf473lnny7v35u.png)

### Testing

Let's test it again. clear console and refresh again. You must see a message Header mounted in the console, now try to navigate to the About page, and Boom 😍.

You see that no more remounting, state loss. We together have just implemented a proper Layout architecture in NextJs.

## Conclusion
You can easily add multiple layouts inside your NextJs app, like Dashboard Layout, etc. You just need to create a Layout, and add common components, like a Sidebar, Dashboard Header, and Dashboard Footer in case of Dashboard Layout. And the next step would be to wrap pages inside this layout.

**Simple isn't it.**

Hopefully, you got some value from this article, in case you have any queries please let me know in the comment section.

Thanks a lot. I am **[Azhar Zaman](https://www.azharzaman.com)** and I will see you in another amazing tutorial like this.

**Till then be safe and try to keep others safe.**