Next.js로 개인프로젝트를 하는 중 공통 레이아웃으로 모든 페이지에 레이아웃을 적용하는게 아닌 각 페이지마다 각각 다른 레이아웃을 적용해야 했다. React만 쓰다가 Next.js로 넘어온 지 얼마 안 돼서 여러모로 익숙지 않아 공식 문서를 보면서 해봤다.
공통 레이아웃 하나로 모든 페이지에 적용하는 방법과 각 페이지마다 개별 레이아웃을 적용하는 방법은 각각 다르다. 상황에 따라 각 방법을 적용하는 법을 알아보자.
https://nextjs.org/docs/pages/building-your-application/routing/pages-and-layouts#layout-pattern
헤더와 푸터를 모든 페이지에 적용하려면 공통 레이아웃을 만들고 _app.tsx에 공통 레이아웃을 적용하면 된다.
components/layout/layout.tsx
import Header from '../header/header';
import Footer from '../footer/footer';
import { ReactNode } from 'react';
export default function AppLayout(props: { children: ReactNode })
{
return (
<>
<Header />
<main>{props.children}</main>
<Footer />
</>
);
}
pages/_app.tsx
import AppLayout from "components/layout/layout";
export default function App({ Component, pageProps }: AppProps) {
return (
<AppLayout>
<Component {...pageProps} />
</AppLayout>
);
}
공통으로 사용할 레이아웃 만든다.
components/layout/layout.tsx
import Header from '../header/header';
import Footer from '../footer/footer';
import { ReactNode } from 'react';
export default function AppLayout(props: { children: ReactNode })
{
return (
<>
<Header />
<main>{props.children}</main>
<Footer />
</>
);
}
개별 페이지에 사용할 레이아웃을 만든다.
components/layout/MypageLayout.tsx
import { ReactNode } from 'react';
import MypageCategory from '../mypage/mypageCategory';
const MypageLayout = (props: { children: ReactNode }) => {
return (
<>
<MypageCategory />
{props.children}
</>
);
};
export default MypageLayout;
_app.tsx에 getLayout 적용하기 위해 설정한다.
pages/_app.tsx
import '../styles/globals.css';
import type { ReactElement, ReactNode } from 'react';
import type { NextPage } from 'next';
import type { AppProps } from 'next/app';
export type NextPageWithLayout = NextPage & {
getLayout?: (page: ReactElement) => ReactNode;
};
type AppPropsWithLayout = AppProps & {
Component: NextPageWithLayout;
};
export default function MyApp({ Component, pageProps }: AppPropsWithLayout) {
const getLayout = Component.getLayout ?? ((page) => page);
return {getLayout(<Component {...pageProps} />)};
}
pages/mypage/index.tsx
import { NextPageWithLayout } from '../_app';
import { ReactElement } from 'react';
import AppLayout from '../../components/layout/layout';
import MypageLayout from '../../components/layout/mypageLayout';
const Mypage: NextPageWithLayout = () => {
return <h1>마이페이지</h1>;
};
Mypage.getLayout = function getLayout(page: ReactElement) {
return (
<AppLayout>
<MypageLayout>{page}</MypageLayout>
</AppLayout>
);
}
export default Mypage;
pages/index.tsx
import { ReactElement } from 'react';
import { NextPageWithLayout } from './_app';
import AppLayout from '../components/layout/layout';
const Home: NextPageWithLayout = () => {
return (
<h1>메인페이지</h1>
);
};
Home.getLayout = function getLayout(page: ReactElement) {
return <AppLayout>{page}</AppLayout>;
};
export default Home;
pages/mypage/heart.tsx
import { NextPageWithLayout } from '../_app';
import { ReactElement } from 'react';
import MypageLayout from '../../components/layout/mypageLayout';
const Heartpage: NextPageWithLayout = () => {
return <h1>좋아요페이지</h1>;
};
Heartpage.getLayout = function getLayout(page: ReactElement) {
return <MypageLayout>{page}</MypageLayout>;ㄴ
}
export default Heartpage;