I want to add a persistent layout to certain pages of my Next.js application. I found this article explaining a couple ways on how someone could do this. It seems pretty straightforward, however I have encountered the following two problems when using the recommended way of doing it:
as any
:const getLayout =
(Component as any).getLayout ||
((page: NextPage) => <SiteLayout children={page} />);
withApollo
HOC (from here) for certain pages. Using this causes Component.getLayout
to always be undefined
. I don't have a good enough understanding of what is going on to know why this is happening (I can guess), so it's difficult to solve this by myself.I have the similar problem and this is how I solved it for my project.
Create a types/page.d.ts
type definition:
import { NextPage } from 'next'
import { ComponentType, ReactElement, ReactNode } from 'react'
export type Page<P = {}> = NextPage<P> & {
// You can disable whichever you don't need
getLayout?: (page: ReactElement) => ReactNode
layout?: ComponentType
}
In your _app.tsx
file,
import type { AppProps } from 'next/app'
import { Fragment } from 'react'
import type { Page } from '../types/page'
// this should give a better typing
type Props = AppProps & {
Component: Page
}
const MyApp = ({ Component, pageProps }: Props) => {
// adjust accordingly if you disabled a layout rendering option
const getLayout = Component.getLayout ?? (page => page)
const Layout = Component.layout ?? Fragment
return (
<Layout>
{getLayout(<Component {...pageProps} />)}
</Layout>
)
// or swap the layout rendering priority
// return getLayout(<Layout><Component {...pageProps} /></Layout>)
}
export default MyApp
The above is just a sample implementation best suited for my use-case, you can switch the type in types/page.d.ts
to fit your needs.