1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Astro でコンテンツコレクションの型(CollectionEntry型)を活かしたコンポーネントを作る

Last updated at Posted at 2024-07-04

この記事の概要

Astro ではsrc/contentにあるディレクトリは 1 つのコンテンツコレクションを表します。
コンテンツコレクションではフロントマターのスキーマを定義・検証できます。

公式ドキュメントでは記事の管理のしやすさやコンテンツコレクションを起点としたルーティングについての記載が多いです。
ただ、自分が触っている中でコンポーネント作成時も便利だと感じたので記事にしました。

CollectionEntry型が便利

コンテンツコレクションとして 1 番よくある、記事管理を想定します。

以下のようにblogコレクションを作成します。
(公式ドキュメントにある内容のままです。)

src/content/config.ts
import { z, defineCollection } from 'astro:content';

const blogCollection = defineCollection({
  type: 'content',
  schema: z.object({
    title: z.string(),
    tags: z.array(z.string()),
    image: z.string().optional(),
  }),
});

export const collections = {
  'blog': blogCollection,
};

ここで、関連記事コンポーネントを作るとしましょう。
以下の要素で作るとします。

  • 画像
    • デフォルト画像を用意しておき、設定されていない記事の場合はそれを使う
  • 記事タイトル
  • タグ
    • たくさんあるときは折り返して表示する

こちらの内容をスキーマの型に沿って作ろうと思う際CollectionEntryが便利です。
イメージを以下に示します。

src/components/RelatedArticle.astro
---
import { Image } from "astro:assets";
import type { CollectionEntry } from "astro:content";

type Props = {
  blog: CollectionEntry<"blog">;
}

const { blog } = Astro.props;
---

<a href={`/${blog.slug}`}>
  <Image
    alt=""
    height="100"
    width="100"
    src={blog.data.image ? {blog.data.image} : "path/to/default/image"}
  />
  <p>{blog.data.title}</p>
  {blog.data.tags.map(tag => (
    <span>{tag}</span>
  ))}
</a>

注目していただきたいのはblog: CollectionEntry<"blog">です。
この記載だけで以下のような情報を取得できています。

const blog: ({
  id: string;
  slug: string;
  body: string;
  collection: "blog"
  data: {
    title: string;
    tags: string[];
    image?: string | undefind
  }
})

dataの中身はsrc/content/config.tsで定義した通りです。
それ以外にも、id や body などを一緒に取得できています。

これにより、あるコンテンツコレクションに適合した型を確実に使える、と言えそうです。

また、コンテンツコレクションを変更すればコンポーネントにも反映されます。
そのため、意図せぬ挙動や表示崩れを防げそうです。

最後に

ドキュメントを読んでいて「これってかなり安全なのでは?」と一人で盛り上がっていました。

しかし、その割には(?)公式ドキュメントではこれだけしか触れられていません。

自分の中では結構良い機能だと思ったので、この記事でもってみなさんに共有します。

追記:

「これだけ」なんて記載しましたが、すみません全然他にもありました。1

  1. X にて教えていただきました。 https://x.com/_yuheiy/status/1808909812287295714

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?