Next.jsのLayoutにpropsを渡したい

はじめに

BB.excite事業部でエンジニアをしている小川です。

はじめに注意書きですが、本記事ではNext.js 12.x の Layouts機能を取り扱います。

Next.jsのPages Routerには同じ要素を再利用するための機能としてLayoutパターンが用意されています。 また、Layoutはページ遷移時に再レンダリングが行われないようになっているため、状態を維持できるようになっていることが特徴的です。

nextjs.org

全てのページに共通して同一のレイアウトということであれば_app.jsなどにLayoutを適用すれば済む話ですが、大抵はページごとに多少の違いを持たせたくなるものです。

今回はレイアウトを変えるほどではないけれど、propsで多少の変更を加えたい!というときにpropsを渡す方法があるのでご紹介です。

Per-Page Layoutsを使ってみる

まずは公式ドキュメントで紹介されているベーシックなLayoutを定義します。

components/BasicLayout.jsx

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

export const BasicLayout = (page) => {
  return (
    <>
      <Navbar />
      <main>{page}</main>
      <Footer />
    </>
  )
}

定義したレイアウトを使うときは以下のような記述になります。

pages/index.jsx

import BasicLayout from '../components/basic-layout'
 
export default const Page = () => {
  return (
    /** Your content */
  )
}
 
Page.getLayout = (page) => BasicLayout(page) // ← ココ

レイアウトの定義をいくつかしておいて、呼び出し側でどのレイアウトを呼び出すか決めれば使い分けられて便利ですね。

propsを渡す

ここからが本題で、Layoutでpropsを受け取れるようにします。

components/basic-layout.jsx

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

export const BasicLayout = (page, props) => {
  return (
    <>
      <Navbar />
      <p>{props}</p>
      <main>{page}</main>
      <Footer />
    </>
  )
}

Layoutを呼び出す側では以下のように記述して渡します。 単純に第2引数で渡すだけですね。

pages/index.jsx

import BasicLayout from '../components/basic-layout'
 
export default const Page = () => {
  return (
    /** Your content */
  )
}

const props = "sample text"
 
Page.getLayout = (page) => BasicLayout(page, props)  // ← ココ

最近のドキュメントやNext.jsのexampleを見ていると以下のような記述もできるようです。

この辺りはお好みでしょうか。

pages/index.jsx

import BasicLayout from '../components/basic-layout'
 
export default const Page = () => {
  return (
    /** Your content */
  )
}
 
Page.getLayout = (page) => {
  <BasicLayout>
    <p>propsを渡さなくてもちょっとした内容であればここに書ける</p>
    {page}
  </BasicLayout>
}