Creating Custom Layouts in Next.js
1 year ago
•
•
3 min read
React's composable nature allows us to create reusable components. Layouts are exactly that! In Next.js there are two ways that you can define a custom layout:
Single Shared Layout
#A Single Shared Layout in Next.js is a custom layout that's used by every page in our app. Let's say our app is simple, and every page has a navbar
and a footer
. We can define our layout like so:
1// src/components/layout/index.tsx23import type { ReactNode } from 'react';45import Navbar from './navbar';6import Footer from './footer';78type Props = {9 children?: ReactNode;10};1112const Layout = ({ children }: Props) => {13 return (14 <>15 <Navbar />16 <main>{children}</main>17 <Footer />18 </>19 );20};2122export default Layout;
In order to use this custom layout, we can wrap the Component
component in our _app.tsx
file:
1// pages/_app.tsx23import type { AppProps } from 'next/app';45import Layout from 'src/components/layout';67const App = ({ Component, pageProps }: AppProps) => {8 return (9 <Layout>10 <Component {...pageProps} />11 </Layout>12 );13};1415export default App;
Since the Layout
component is reused when changing pages, its component state will be preserved.
Per-Page Layouts
#If we want to have multiple layouts (ex. authentication, dashboard, settings etc...), we can define a getLayout
property to our pages that will receive the page in props
, and wrap it in the layout that we want. Since we're returning a function, we can have complex nested layouts if we wanted to.
Here's an example of a page:
1// pages/index.tsx23import type { ReactElement } from 'react'45import Layout from 'src/components/layout'6import NestedLayout from 'src/components/nested-layout'78const Page = () => {9 return (10 // Our page's content...11 )12}1314Page.getLayout = (page: ReactElement) => {15 return (16 <Layout>17 <NestedLayout>{page}</NestedLayout>18 </Layout>19 )20}2122export default Page
In order to use this, we need to make some changes in our _app.tsx
:
1// pages/_app.tsx23import type { ReactElement, ReactNode } from 'react';4import type { NextPage } from 'next';5import type { AppProps } from 'next/app';67type NextPageWithLayout = NextPage & {8 // define the getLayout method for every page9 getLayout?: (page: ReactElement) => ReactNode;10};1112type AppPropsWithLayout = AppProps & {13 // override the default Component definition14 Component: NextPageWithLayout;15};1617const App = ({ Component, pageProps }: AppPropsWithLayout) => {18 // use the getLayout defined in each page19 // if it doesn't exist, provide a fallback20 const getLayout = Component.getLayout ?? ((page) => page);2122 return getLayout(<Component {...pageProps} />);23};2425export default App;
Have in mind that the Custom Layouts are not considered as Pages, so the only way to fetch data is on the client-side.
That's how we can setup a simple mechanism for custom per-page layouts.
Subscribe to my newsletter ✉️
Get emails from me about web development, content creation, and whenever I publish new content.
Subscribe on Substack