티스토리 뷰
최상위 컴포넌트인 App 컴포넌트를 먼저 살펴보자.
// _app.tsx
import "@/styles/globals.css";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<Component {...pageProps} />
);
}
App 컴포넌트가 전달받는 props 중 Component라는 props는 현재 접속하는 페이지 컴포넌트이다.
따라서 모든 페이지의 적용될 레이아웃이 있다면 App 컴포넌트와 같이 최상위 컴포넌트에 적용해주면 된다.
// global-layout.tsx : 모든 페이지에 적용할 레이아웃
import Link from "next/link";
import { ReactNode } from "react";
import style from "./global-layout.module.css";
export default function GlobalLayout({ children }: { children: ReactNode }) {
return (
<div className={style.container}>
<header className={style.header}>
<Link href={"/"}>📚 ONEBITE BOOKS</Link>
</header>
<main className={style.main}>{children}</main>
<footer className={style.footer}>제작 @2024</footer>
</div>
);
}
// _app.tsx : 최상위 컴포넌트
import GlobalLayout from "@/components/global-layout";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
return (
<GlobalLayout>
<Component {...pageProps} />
</GlobalLayout>
);
}
특정 페이지에만 적용할 레이아웃은 레이아웃을 적용할 페이지의 컴포넌트에 getLayout이라는 속성을 추가해서 적용할 수 있다.
App 컴포넌트에서 페이지 컴포넌트를 바로 리턴하지 않고 페이지 컴포넌트의 getLayout 메서드의 인수로
페이지 컴포넌트를 넣어주면 특정 페이지에 원하는 레이아웃을 적용할 수 있다.
// searchable-layout.tsx : Home 페이지에만 적용할 레이아웃
import { ReactNode } from "react";
export default function SearchableLayout({ children }: { children: ReactNode }) {
return (
<div>
<div>임시 서치바</div>
{children}
</div>
);
}
// index.tsx : 레이아웃을 적용할 페이지
import SearchableLayout from "@/components/searchable-layout";
import style from "./index.module.css";
import { ReactNode } from "react";
export default function Home() {
return (
<>
<h1 className={style.h1}>인덱스</h1>
</>
);
}
Home.getLayout = (page: ReactNode) => {
return <SearchableLayout>{page}</SearchableLayout>;
};
// _app.tsx : 최상위 컴포넌트
import GlobalLayout from "@/components/global-layout";
import "@/styles/globals.css";
import type { AppProps } from "next/app";
export default function App({ Component, pageProps }: AppProps) {
const getLayout = Component.getLayout;
return (
<GlobalLayout>
{getLayout(<Component {...pageProps} />)}
</GlobalLayout>
);
}
위와 같이 작성하면 getLayout를 설정하지 않은 페이지로 접근하면 getLayout값이 undefined이기 때문에
오류가 발생한다.
// _app.tsx
// ...
const getLayout = Component.getLayout; // undefined
// ...
이 오류는 특정 레이아웃을 사용하지 않는 페이지(getLayout을 설정하지 않은 페이지)에서는
getLayout이라는 변수에 Component.getLayout 대신 page를 그대로 리턴하는 함수를 넣어 예외처리를 통해 해결할 수 있다.
// _app.tsx
// ...
const getLayout = Component.getLayout ?? ((page: ReactNode) => page);
// ...
타입스크립트까지 적용하면
import GlobalLayout from "@/components/global-layout";
import "@/styles/globals.css";
import { NextPage } from "next";
import type { AppProps } from "next/app";
import { ReactNode } from "react";
type NextPageWithLayout = NextPage & {
getLayout?: (page: ReactNode) => ReactNode;
};
export default function App({
Component,
pageProps,
}: AppProps & {
Component: NextPageWithLayout;
}) {
const getLayout = Component.getLayout ?? ((page: ReactNode) => page);
return <GlobalLayout>{getLayout(<Component {...pageProps} />)}</GlobalLayout>;
}
참고자료
반응형
'개발공부 > ⬛ Next.js' 카테고리의 다른 글
[Next.js] SEO 적용하기[Next.js] SEO 적용하기 (Using Pages Router) (4) | 2024.09.16 |
---|---|
[Next.js] data fetching 및 사전 렌더링 방식 3가지 (Using Pages Router) (1) | 2024.09.11 |
[Next.js] 스타일링 (2) | 2024.09.07 |
[Next.js] 프리페칭 (Pre-fetching) (0) | 2024.09.04 |
[Next.js] 네비게이팅 (Navigating) (0) | 2024.09.04 |
개발자 삐롱히
프론트엔드 개발자 삐롱히의 개발 & 공부 기록 블로그