v2.8.2

Pages

src/pages 配下はファイルベースルーティングに対応したページファイルを作成できます。使用できる拡張子は .tsx .jsxexport default が必須です。Markdownで書くこともできます。

import type { MinistaLocation } from "minista"

type PageProps = {
  location: MinistaLocation
}

const PageHome = ({ location }: PageProps) => {
  return <h1>Home</h1>
}

export default PageHome

CAUTION

  • import した CSS は bundle.css として結合し全体に適応されます
  • 静的ビルドされるため React の Hook を使用することはできません
  • React の Hook は Partial Hydration で使用できます

location

// src/pages/docs/index.tsx
export default ({ location }) => {
  return <>{location.pathname}</>
}
// => "/docs/"

ページファイルは props から location.pathname を取得可能です。リンクに付与する activeClass などに使えます。

getStaticData

ページファイルは非同期関数 getStaticData で Next.js の getStaticProps + getStaticPaths を再現できます。簡単な例として、GitHub Issues の API を叩いて一覧と詳細ページを作ってみましょう。

まずは、src/pages/issues/index.tsxsrc/pages/issues/[number].tsx を作成します。詳細ページのテンプレートは Next.js と同じくファイル名にブラケッツを用いて渡す path 名を入れます。ブラケッツはディレクトリにも使え、src/pages/issues/[number]/index.tsx にもできます。

src
└── pages
    └── issues
        ├── index.tsx
        └── [number].tsx

src/pages/issues/index.tsxgetStaticDatafetch を使い Issues 一覧の配列を取得。オブジェクトで返した props をそのページで使用できます。

// src/pages/issues/index.tsx
export const getStaticData = async () => {
  const apiUrl = "https://api.github.com/repos/qrac/minista/issues"
  const apiParamsQuery = "?state=all&creator=qrac&per_page=5"
  const response = await fetch(apiUrl + apiParamsQuery)
  const data = await response.json()
  return {
    props: {
      issues: data,
    },
  }
}

type PageIssuesProps = {
  issues?: { title: string; number: number }[]
}

const PageIssues = (props: PageIssuesProps) => {
  return (
    <>
      <h1>Issues</h1>
      <ul>
        {props.issues?.map((item, index) => (
          <li key={index}>
            <a href={`/issues/${item.number}/`}>{item.title}</a>
          </li>
        ))}
      </ul>
    </>
  )
}

export default PageIssues

同様に src/pages/issues/[number].tsxgetStaticDatafetch を使います。一覧と少し異なり、propspaths を持った配列を返します。以下の例ですと item.number[number].tsx に使用され、item.number の合致した props が詳細ページのテンプレートに流し込まれます。

// src/pages/issues/[number].tsx
export const getStaticData = async () => {
  const apiUrl = "https://api.github.com/repos/qrac/minista/issues"
  const apiParamsQuery = "?state=all&creator=qrac&per_page=5"
  const response = await fetch(apiUrl + apiParamsQuery)
  const data = await response.json()
  return data.map((item: PageIssuesTemplateProps) => ({
    props: item,
    paths: { number: item.number },
  }))
}

type PageIssuesTemplateProps = {
  title: string
  body: string
  number: number
}

const PageIssuesTemplate = (props) => {
  return (
    <>
      <h1>{props.title}</h1>
      <div>{props.body}</div>
    </>
  )
}

export default PageIssuesTemplate

余談ですが、上記の GitHub Issues API の例では props.body がリッチテキストではないため Markdown のまま出力されてしまいます。HTML に変換する方法は多数ありますが minista-markdown を使うと比較的簡単に変換できるのでおすすめです。