Layouts
Examples
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 navigation bar and footer on every page.
JSX1// components/layout.js23import Navbar from './navbar'4import Footer from './footer'56export default function Layout({ children }) {7 return (8 <>9 <Navbar />10 <main>{children}</main>11 <Footer />12 </>13 )14}
Examples
Single Shared Layout with Custom App
If you only have one layout for your entire application, you can create a Custom App and wrap your application with the layout. Since the <Layout />
component is re-used when changing pages, its component state will be preserved (e.g. input values).
JSX1// pages/_app.js23import Layout from '../components/layout'45export default function MyApp({ Component, pageProps }) {6 return (7 <Layout>8 <Component {...pageProps} />9 </Layout>10 )11}
Per-Page Layouts
If you need multiple layouts, you can add a property getLayout
to your page, allowing you to return a React component for the layout. This allows you to define the layout on a per-page basis. Since we're returning a function, we can have complex nested layouts if desired.
JSX1// pages/index.js23import Layout from '../components/layout'4import NestedLayout from '../components/nested-layout'56export default function Page() {7 return {8 /** Your content */9 }10}1112Page.getLayout = function getLayout(page) {13 return (14 <Layout>15 <NestedLayout>{page}</NestedLayout>16 </Layout>17 )18}
JSX1// pages/_app.js23export default function MyApp({ Component, pageProps }) {4 // Use the layout defined at the page level, if available5 const getLayout = Component.getLayout || ((page) => page)67 return getLayout(<Component {...pageProps} />)8}
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 state.
Note: This process is called reconciliation, which is how React understands which elements have changed.
With TypeScript
When using TypeScript, you must first create a new type for your pages which includes a getLayout
function. Then, you must create a new type for your AppProps
which overrides the Component
property to use the previously created type.
TSX1// pages/index.tsx23import type { ReactElement } from 'react'4import Layout from '../components/layout'5import NestedLayout from '../components/nested-layout'67export default function Page() {8 return {9 /** Your content */10 }11}1213Page.getLayout = function getLayout(page: ReactElement) {14 return (15 <Layout>16 <NestedLayout>{page}</NestedLayout>17 </Layout>18 )19}
TSX1// pages/_app.tsx23import type { ReactElement, ReactNode } from 'react'4import type { NextPage } from 'next'5import type { AppProps } from 'next/app'67type NextPageWithLayout = NextPage & {8 getLayout?: (page: ReactElement) => ReactNode9}1011type AppPropsWithLayout = AppProps & {12 Component: NextPageWithLayout13}1415export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {16 // Use the layout defined at the page level, if available17 const getLayout = Component.getLayout ?? ((page) => page)1819 return getLayout(<Component {...pageProps} />)20}
Data Fetching
Inside your layout, you can fetch data on the client-side using useEffect
or a library like SWR. Because this file is not a Page, you cannot use getStaticProps
or getServerSideProps
currently.
JSX1// components/layout.js23import useSWR from 'swr'4import Navbar from './navbar'5import Footer from './footer'67export default function Layout({ children }) {8 const { data, error } = useSWR('/api/navigation', fetcher)910 if (error) return <div>Failed to load</div>11 if (!data) return <div>Loading...</div>1213 return (14 <>15 <Navbar links={data.links} />16 <main>{children}</main>17 <Footer />18 </>19 )20}
For more information on what to do next, we recommend the following sections: