Astro.js 小ネタ集 その7 記事をタグで検索
前回に引き続きAstro.jsでの小ネタを紹介していきます。
ここでは前回紹介したJSON コレクションを使ったブログ記事のタグ検索機能についてご紹介いたします。
タグ検索機能の追加
タグのコレクションが定義できましたので、続いてタグでの検索機能を追加してみます。 これは以下の公式のチュートリアルを参考にしております。
チュートリアルの src/pages/tags/[tag].astro
を以下に再掲します。
import BaseLayout from '../../layouts/BaseLayout.astro'; export async function getStaticPaths() { return [ { params: { tag: "astro" } }, { params: { tag: "successes" } }, { params: { tag: "community" } }, { params: { tag: "blogging" } }, { params: { tag: "setbacks" } }, { params: { tag: "learning in public" } }, ]; } const { tag } = Astro.params; --- <BaseLayout pageTitle={tag}> <p>Posts tagged with {tag}</p> </BaseLayout>
これの第一のミソはファイル名が [tag].astro
となっている点です。これがgetStaticPaths()
の戻り値の[{ params: { tag: 'astro' } }, ...]
に対応しています。
ファイル名を [id].astro
とした場合には [{ params: { id: ... } },]
としなければなりません。
このようにparams
はファイルのパスのプレースホルダと対応しています。
例えばsrc/pages/[content]/[id].astro
のgetStaticPaths()
では、[{ params: { content: 'sample' , id: '1' } }, ...]
のようなデータを返す必要があります。
個人ブログのほうでは src/pages/tags/[id].astro
としていますので、以下のようになっております。
... export async function getStaticPaths() { return Promise.all([...(await getCollection('blog')) ... ].map(async (tag) => { const e = await getEntry('tags', tag); return e ? { params: { id: e.id, }, props: { tag: e.id, tagName: e.data.title, icon: e.data.icon, } } : { params: { id: tag, }, props: { tag, tagName: tag, icon: '', } } }) ); } interface Props { tag: string; tagName: string; icon: string; }; const { tag, tagName, icon } = Astro.props as Props; const blog = await getCollection('blog', (blog) => blog.data.tags.includes(tag));
のような感じで使用しています。
getStaticPaths()
でユニークなタグのリストを生成するところは先ほどと同じで、続いて読み取ったJSONから { params:{id: e.id,}, props: {tag: e.id, tagName: e.data.title, icon: e.data.icon,}}
形式のオブジェクトに変換しています。
このオブジェクトの後半の props
の箇所が、interface Props {...}; const { tag, tagName, icon } = Astro.props as Props;
で渡されてきます。
そして最後のconst blog = await getCollection('blog', (blog) => blog.data.tags.includes(tag));
でタグが指定されているブログの一覧を作成しています。
今回はここまでといたします。
個人ブログでも記事をあげています。こちらもあわせてご覧ください!