Next.js

Posted: February 18, 2022

Basic Features: データ取得 | Next.js
このドキュメントはNext.jsのバージョン9.3以降が対象となります。旧バージョンのNext.jsを使用している場合は、 以前のドキュメント を参照してください。 Pagesのドキュメントにおいて、Next.js には 2 種類のプリレンダリングがあることを説明しました。 静的生成と サーバーサイドレンダリングです。このページでは、それぞれの場合でのデータ取得戦略について掘り下げていきます。 まず最初に Pagesのドキュメントを読む ことをお勧めします。 プリレンダリングのデータ取得に使える 3 つの特徴的な Next.js の関数についてお話します: また、クライアント側でのデータ取得について簡潔にお話します。 ページから getStaticProps という async 関数をエクスポートすると、Next.js はビルド時に getStaticProps から返される props を使ってプリレンダリングします。 context パラメータは次のキーを含むオブジェクトです: paramsはページが動的ルートを利用するためのルートパラメータを持ちます。たとえば、ページ名が [id].js である時、paramsは { id: ...} のように見えます。詳細は 動的ルーティングのドキュメントをご覧ください。後に説明する getStaticPathsと一緒に使う必要があります。 ページがプレビューモードになっている時は preview が true になり、そうでない場合は false になります。プレビューモードのドキュメントをご覧ください。 previewDataは、setPreviewDataによって設定されたプレビューデータを含みます。プレビューモードのドキュメント をご覧ください。 getStaticPropsを使って CMS(コンテンツマネジメントシステム)からブログ記事の一覧を取得する例です。この例は

Notion blogのソースを見ていて、以下のような感じのコードがあったので、この「getStaticProps」っていつ実行されてるんだ?と思ったら、これはNext.js組み込みの関数のようで、ビルド時にデータを取得してくるようだ。

export async function getStaticProps({ preview }) {
  const postsTable = await getBlogIndex()

  const authorsToGet: Set<string> = new Set()
  const posts: any[] = Object.keys(postsTable)
    .map((slug) => {
      const post = postsTable[slug]
      // remove draft posts in production
      if (!preview && !postIsPublished(post)) {
        return null
      }
      post.Authors = post.Authors || []
      for (const author of post.Authors) {
        authorsToGet.add(author)
      }
      return post
    })
    .filter(Boolean)

  const { users } = await getNotionUsers([...authorsToGet])

  posts.map((post) => {
    post.Authors = post.Authors.map((id) => users[id].full_name)
  })

  return {
    props: {
      preview: preview || false,
      posts,
    },
    revalidate: 10,
  }
}

const Index = ({ posts = [], preview }) => {
  return (
    <>
      <Header titlePre="Blog" />
      {preview && (
        <div className={blogStyles.previewAlertContainer}>
          <div className={blogStyles.previewAlert}>
            <b>Note:</b>
            {` `}Viewing in preview mode{' '}
            <Link href={`/api/clear-preview`}>
              <button className={blogStyles.escapePreview}>Exit Preview</button>
            </Link>
          </div>
        </div>
      )}
      <div className={`${sharedStyles.layout} ${blogStyles.blogIndex}`}>
        <h1>My Notion Blog</h1>
        {posts.length === 0 && (
          <p className={blogStyles.noPosts}>There are no posts yet</p>
        )}
        {posts.map((post) => {
          return (
            <div className={blogStyles.postPreview} key={post.Slug}>
              <h3>
                <span className={blogStyles.titleContainer}>
                  {!post.Published && (
                    <span className={blogStyles.draftBadge}>Draft</span>
                  )}
                  <Link href="/blog/[slug]" as={getBlogLink(post.Slug)}>
                    <a>{post.Page}</a>
                  </Link>
                </span>
              </h3>
              {post.Authors.length > 0 && (
                <div className="authors">By: {post.Authors.join(' ')}</div>
              )}
              {post.Date && (
                <div className="posted">Posted: {getDateStr(post.Date)}</div>
              )}
              <p>
                {(!post.preview || post.preview.length === 0) &&
                  'No preview available'}
                {(post.preview || []).map((block, idx) =>
                  textBlock(block, true, `${post.Slug}${idx}`)
                )}
              </p>
            </div>
          )
        })}
      </div>
    </>
  )
}

export default Index

参考リンクより、

プリレンダリングのデータ取得に使える 3 つの特徴的な Next.js の関数についてお話します: