Layouts

oasis·2023년 4월 27일
1

Next.js

목록 보기
2/3
post-thumbnail

Basic Features: Layouts | Next.js

진행중인 프로젝트에서 next.js를 사용하기에, SSG와 SSR개념을 명확하게 이해하기 위해서 공식문서를 번역하여 공부한 내용입니다.



개요


  • 모든 페이지에 네비게이션 바와 푸터가 공통으로 적용되는 경우
// components/layout.js

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

export default function Layout({ children }) {
  return (
    <>
      <Navbar />
      <main>{children}</main>
      <Footer />
    </>
  )


예시


하나의 레이아웃이 모든 페이지에 적용되는 경우

  • 전체 앱에 하나의 레이아웃만 가지는 경우, _app.js에서레이아웃 설정 가능
  • <Layout /> 컴포넌트가 페이지마다 재사용되더도, 컴포넌트의 상태는 계속 유지됨
// pages/_app.js

import Layout from '../components/layout'

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

페이지마다 다른 레이아웃이 적용되는 경우

  • 페이지에 getLayout이라는 속성 추가 가능함 → 페이지마다 레이아웃 정의 가능함
  • 중첩 레이아웃도 사용 가능
// pages/index.js

import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'

export default function Page() {
  return (
    /** Your content */
  )
}

Page.getLayout = function getLayout(page) {
  return (
    <Layout>
      <NestedLayout>{page}</NestedLayout>
    </Layout>
  )
}
// pages/_app.js

export default function MyApp({ Component, pageProps }) {
  // Use the layout defined at the page level, if available
  const getLayout = Component.getLayout || ((page) => page)
	
// getLayout함수로 전체 컴포넌트를 감싸줌
  return getLayout(<Component {...pageProps} />)
}
  • 페이지 이동하면서,페이지의 상태를 유지해야하는 경우가 있음 → 위 레이아웃 패턴을 이용하면 상태 유지가 가능함 → 리액트 컴포넌트 트리가 페이지 전환시 유지되기 때문 참고: React Tree Preserving and Resetting State – React



Typescript


  1. getLayout 함수를 포함하는 새로운 타입을 만들기
  2. 1에서 만들어진 타입을 사용하기 위한 AppProps 타입 만들기
    • Component 속성을 오버라이드함
// pages/index.tsx

import type { ReactElement } from 'react'
import Layout from '../components/layout'
import NestedLayout from '../components/nested-layout'
import type { NextPageWithLayout } from './_app'

const Page: NextPageWithLayout = () => {
  return <p>hello world</p>
}

Page.getLayout = function getLayout(page: ReactElement) {
  return (
    <Layout>
      <NestedLayout>{page}</NestedLayout>
    </Layout>
  )
}

export default Page
// pages/_app.tsx

import type { ReactElement, ReactNode } from 'react'
import type { NextPage } from 'next'
import type { AppProps } from 'next/app'

export type NextPageWithLayout<P = {}, IP = P> = NextPage<P, IP> & {
  getLayout?: (page: ReactElement) => ReactNode
}

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout
}

export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
  // page component에 layout이 있으면 쓰고, 아니면 page 그대로 리턴
  const getLayout = Component.getLayout ?? ((page) => page)

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

0개의 댓글