💫

next/headの気を付けたい仕様

2022/03/04に公開

ページのheadを実装していて、文法は間違っていないはずなのに一部の要素が出力されていないことに気づき、調べてみたら以下の仕様を見つけました。ESLintにも型チェックにも引っかからず、アプリケーションは普通に起動するので気づかないままなんてこともありえます。

気を付けたい仕様

条件を満たさない要素は取得しない

条件

  • Head要素の直下の子要素
  • <React.Fragment>か配列でラップされている1階層の要素

title, meta or any other elements (e.g. script) need to be contained as direct children of the Head element, or wrapped into maximum one level of <React.Fragment> or arrays—otherwise the tags won't be correctly picked up on client-side navigations.

公式サイト引用

ダメな例

複数ページで使う要素を子コンポーネントして切り出す

PageHead.tsx
import Head from 'next/head'
import { VFC } from 'react'
import ChildHead from './ChildHead'

const PageHead: VFC = () => {
  return (
    <Head>
      <title>ページタイトル</title>
      <ChildHead />
    </Head>
  )
}

export default PageHead
ChildHead.tsx
import { VFC } from 'react'

const ChildHead: VFC = () => {
  return (
    <>
      <link rel="icon" href="/favicon.ico" />
      <meta property="twitter:card" content="summary_large_image" />
    </>
  )
}

export default ChildHead

yarn devなどでアプリケーションを起動してブラウザの検証ツールで確認するとChildHeadコンポーネントの要素(link, meta)が出力されていないことがわかります。

良い例

childrenを活用してHead要素の直下で展開させる

PageHead.tsx
import { VFC } from 'react'
import ChildHead from './ChildHead'

const PageHead: VFC = () => {
  return (
    <ChildHead>
      <title>ページタイトル</title>
    </ChildHead>
  )
}

export default PageHead
ChildHead.tsx
import Head from 'next/head'
import { ReactNode, VFC } from 'react'

type Props = { children: ReactNode }

const ChildHead: VFC<Props> = ({ children }) => {
  return (
    <Head>
      <link rel="icon" href="/favicon.ico" />
      <meta property="twitter:card" content="summary_large_image" />
      {children}
    </Head>
  )
}

export default ChildHead

この書き方であればtitle, link, metaの3つの要素が出力されます。

最後に

皆さんの開発しているプロダクトでは期待した全てのheadの要素が出力されていますか?

Discussion