[Next.js] 페이지별 레이아웃 적용하기 (Per-Page Layouts) (feat. TypeScript)

hzn·2023년 4월 26일
0

PROJECT🏝

목록 보기
21/24
post-thumbnail
post-custom-banner

페이지 별로 적용되는 레이아웃이 다를 경우 Per-Page Layouts을 적용할 수 있다.

  • 모든 페이지에 Footer
  • Main, Addnew 페이지에 Header를 적용하려고 한다.

1. 공통 레이아웃 만들기

  • 모든 페이지에 포함될 Footer가 적용된 레이아웃을 만든다

comonents > layout > Layout.tsx

import Footer from '../footer/Footer';
import { ReactNode } from 'react';
...
const Layout = (props: { children: ReactNode }) => {
  return (
    <Wrapper>
      {props.children}
      <Footer />
    </Wrapper>
  );
};
}

2. 개별 레이아웃 만들기

  • Main, Addnew 페이지에 적용될 Header 레이아웃을 만든다.

comonents > layout > HeaderLayout.tsx

import Header from '../header/Header';
import { ReactNode } from 'react';

const HeaderLayout = (props: { children: ReactNode }) => {
  return (
    <>
      <Header />
      {props.children}
    </>
  );
};

export default HeaderLayout;

3. getLayout 적용 설정 (_app.tsx)

pages > _app.tsx

...
import type { ReactElement, ReactNode } from 'react';
import type { NextPage } from 'next';

// 각 페이지에서 불러와서 쓸 '레이아웃 적용된 페이지의 type'
export type NextPageWithLayout = NextPage & {
  getLayout?: (page: ReactElement) => ReactNode;
};

type AppPropsWithLayout = AppProps & {
  Component: NextPageWithLayout;
};

export default function App({ Component, pageProps }: AppPropsWithLayout) {
  // 페이지 단위에서 getLayout을 적용할 지 말지 결정
  const getLayout = Component.getLayout ?? ((page) => page);

  return (
    <Provider store={store}>
      <ThemeProvider theme={theme}>
        <GlobalStyle />
          <main className={jetBrains_Mono.className}>
             {getLayout(<Component {...pageProps} />)} // Component에 getLayout 적용
          </main>
      </ThemeProvider>
    </Provider>
  );
}

4. 개별 페이지에서 getLayout으로 레이아웃 적용

공통 레이아웃만 적용

  • 로그인, 회원가입 페이지는 Footer만 적용 (공통 레이아웃만 적용)
import type { ReactElement } from 'react';
import Layout from '../../components/layout/Layout';
import type { NextPageWithLayout } from '../_app';

const LoginPage: NextPageWithLayout = () => {
...생략
};

 // getLayout으로 해당 페이지에 필요한 레이아웃 적용
LoginPage.getLayout = function getLayout(page: ReactElement) {
  return <Layout>{page}</Layout>; // 공통 레이아웃만 적용
};

export default LoginPage;

공통 + 개별 레이아웃 적용

  • 메인, Addnew 페이지는 Footer(공통) + Header(개별) 적용

pages > addnew > index.tsx

import type { ReactElement } from 'react';
import Layout from '../../components/layout/Layout';
import HeaderLayout from '../../components/layout/HeaderLayout';
import type { NextPageWithLayout } from '../_app'; // 레이아웃 적용된 페이지의 타입  (불러오기) 

const AddNew: NextPageWithLayout = () => { // (적용)
  return (
    <>
     ...생략
    </>
  );
};

// getLayout으로 해당 페이지에 필요한 레이아웃 적용
AddNew.getLayout = function getLayout(page: ReactElement) {
  return (
    <Layout>
      <HeaderLayout>{page}</HeaderLayout> // 공통 + 개별 레이아웃 적용
    </Layout>
  );
};

export default AddNew;
post-custom-banner

0개의 댓글