Guide to Layouts and Page Specific Layouts in NextJS
Tags: webdev, javascript, beginners, react
Published: 2022-11-30 19:53:23

Layouts are a powerful abstract concept in NextJS. 

It is a declarative way of telling Next the general layout of your pages without reusing code. Most commonly, this is just a navbar and a footer.

However, some use cases require pages to have their own layouts, rather than one for every single page. Some even require nested layouts!

Personally, I found it rather confusing trying to figure out how layouts work when I was getting started. Let me break it down for you.

If you haven't used layouts in NextJS, this is how they work.

```javascript
import Navbar from './navbar'
import Footer from './footer'

export default function Layout({ children }) {
  return (
    <>
      <Navbar />
      <main>{children}</main>
      <Footer />
    </>
  )
}
```
This is your standard Layout component. Here we are passing a React component as props, and rendering it in between a Navbar and a Footer. 

Children is going to be the page components that are being passed as props. This will come from your main app component.

In order to use this, we can import it in app and pass our page components as props like so:

```javascript
import Layout from '../components/layout'

export default function MyApp({ Component, pageProps }) {
  return (
    <Layout>
      <Component {...pageProps} />
    </Layout>
  )
}
```

For those new to React, this is an example of a [higher order component](https://reactjs.org/docs/higher-order-components.html)

Now that you have imported and used the Layout component, all of your pages from app are going to be formatted as you did in the layout definition. In this case, they will all have a ``<Navbar>`` above and a ``<Footer>`` below.

But what if you need a different layout? What if some pages need to have a sidebar as well as the ``<Navbar>`` and ``<Footer>``?

{% twitter 1595762654530129920 %}

This is called a page specific layout. There are a lot of different ways to implement this, and some have their own advantages and disadvantages. But I think the simplest and most effective way is by creating a new property for our page components.

First, make the layout. You can do so just like the first example. Import the component that you want to incorporate in the layout, then declare children as props.

```javascript
import React from "react";
import Sidebar from "../comps/sidebar";

export const SidebarLayout = ({ children }) => {
  return (
    <div>
      <Sidebar />
      {children}
    </div>
  );
};

export default SidebarLayout;
```

Above, we declared that the ``<Sidebar>`` is going to live above the components. Now in order to actually render this to the screen, it's going to be a little different.

First, in the component that needs a specific layout, import the layout.

Then you need to give it a new property. I like to use PageLayout. I do this at the bottom of the component before my exports.

```javascript
import React from "react";
import SnapshotLayout from "../layouts/snapshot";

const MyNotes = (props: any) => {
  return (
    <div>
      <textarea placeholder="Write notes here!"></textarea>
    </div>
  );
};

MyNotes.PageLayout = SnapshotLayout;

export default MyNotes;
```

By adding ``MyNotes.PageLayout = SnapshotLayout;``, we have given our new JSX element the property PageLayout. It's value is the layout we just made. This isn't going to render correctly though - Next doesn't know what to do with this information yet.

Now in order to render the correct layout for each page, let's add logic for it in App.

```javascript
import React from "react";
import Layout from "../components/layout";
import "../styles/globals.css";

const MyApp = ({ Component, pageProps } ) => {
  return (
    <Layout>
      {Component.PageLayout ? (
        <Component.PageLayout>
          <Component {...pageProps} />
        </Component.PageLayout>
      ) : (
        <Component {...pageProps} />
      )}
    </Layout>
  );
};

export default MyApp;
```

Here, we have done two things. First we make a ternary statement. We check if the property PageLayout exists on a component. If so, render it with the PageLayout as a higher order component.

If not, simply render it without the page specific layout.

This works because we defined the property PageLayout in our component. When App retrieves a component, it's properties become accessible. The layout becomes it's own component because we extract it and declare it as a component. ``<Component.PageLayout>`` in this example would be the same as writing ``<SidebarLayout>``.

The advantage of rendering layouts this way is scalability. Say you want to make more layouts for pages. All you have to do is create the layout, and import it in your component, and set it as the value of the component's PageLayout property.

Still confused? Typescript user? Watch this amazing video! It's a great, clear explanation of NextJS layouts and how to render them conditionally!

{% youtube WOeLxL2DF3E %}

This is the repository for today's blogpost: https://github.com/professorjrod/layout-test

Thanks so much for reading! This article was a doozy, honestly. Page layouts ain't easy! If you enjoyed this blog post consider giving me a like so other people can find this resource :)

Have a great day and HAPPY CODING!!!