Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Persistent layouts by default #242

Open
mcavaliere opened this issue Dec 3, 2021 · 1 comment
Open

Persistent layouts by default #242

mcavaliere opened this issue Dec 3, 2021 · 1 comment

Comments

@mcavaliere
Copy link

To keep page transitions snappy, we should be using page layout components and static getLayout methods. This allows us to have centralized header/footer content that doesn't get re-rendered when going from one page to another.

To see them in action, navigate back and forth from this article index page and any of the articles.

This article I wrote, Next.js Page Layouts and Dynamic Content shows how to inject dynamic page-specific content into the layouts and still have them equally snappy.

@tundera
Copy link
Contributor

tundera commented Dec 8, 2021

I really like this method of assigning layout functions to the page modules as a property. This worked pretty well in a JS app but it got kind of tricky for TS apps. Blitz.js does something pretty similar for their pages and layouts so I looked at their source to figure out how to make this technique work in a Next.js app with TypeScript. You can write a types/index.ts file and add:

import type { AppProps as NextAppProps } from 'next/app'
import type {
  NextComponentType as DefaultNextComponentType,
  NextPage as DefaultNextPage,
  NextPageContext,
} from 'next'

export type GetLayoutFunction = (component: JSX.Element) => JSX.Element

export declare type NextComponentType<
  C = NextPageContext,
  IP = Record<string, unknown>,
  P = Record<string, unknown>,
> = DefaultNextComponentType<C, IP, P>

export interface AppProps<P = Record<string, unknown>> extends NextAppProps<P> {
  Component: NextComponentType<NextPageContext, any, P> & {
    getLayout?: GetLayoutFunction
  }
}

export declare type NextPage<P = Record<string, unknown>, IP = P> = DefaultNextPage<P, IP> & {
  getLayout?: GetLayoutFunction
}

In _app.tsx import the AppProps type from the custom type definitions:

// Old type import 
// import type { AppProps } from 'next/app'

// New type import
import type { AppProps } from 'types'

function MyApp({ Component, pageProps }: AppProps) {
  const getLayout = Component.getLayout || ((page) => page)

  return getLayout(<Component {...pageProps} />)
}

export default MyApp

Then in a page files use the custom NextPage definition:

// Old type import
// import type { NextPage } from 'next'

// New type import
import type { NextPage } from '../types'

const HomePage: NextPage = () => {
  ...

Then the type errors are gone 😅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants