astroのparamsの挙動検証

2023/11/21に公開

結論

astroのgetStaticPaths()実施時、戻り値に使用するparamsは、ファイル名に使われていない場合にファイル内でimportして利用することはできない

生成されるページ内へ変数を送信したい場合は、getStaticPaths()の戻り値にpropsを定義する必要がある。

実験内容

paramsを複数定義/ファイル名に一つの値のみ使用

以下のような操作を実験してみました。

[pageName].astro
---
const { pageindex, pageTitle, pageName } = Astro.params;
export interface staticPath {
    params: {
        pageName: string,
        pageindex: number,
        pageTitle: string, 
    }
}
export async function getStaticPaths() {
    let staticPaths: staticPath[] = [];
    for (let i = 0; i < 10; i++){
        staticPaths.push({
            params: {
                pageindex: i,
                pageTitle: "Post [" + String(i + 1).padStart(2, '0') + "]",
                pageName:  "post-" + String(i + 1).padStart(2, '0'),
            }    
        })
    }
    return staticPaths;
}
---
pageName={pageName}<br />
pageindex={pageindex}<br />
pageTitle={pageTitle}<br />

上記の結果、次のように出力されました。
pageindexおよびpageTitleは値が挿入されませんでした。

paramsで定義された値の状態確認

表示されなかった値がどのような扱いなのかを確認しました。

[pageName].astro
---
const { pageindex, pageTitle, pageName } = Astro.params;
export interface staticPath {
    params: {
        pageName: string | undefined, // 念のためundefinedを許容しています。
        pageindex: number | undefined,
        pageTitle: string | undefined,
    }
}
export async function getStaticPaths() {
    let staticPaths: staticPath[] = [];
    for (let i = 0; i < 10; i++){
        staticPaths.push({
            params: {
                pageindex: i,
                pageTitle: "Post [" + String(i + 1).padStart(2, '0') + "]",
                pageName:  "post-" + String(i + 1).padStart(2, '0'),
            }    
        })
    }
    return staticPaths;
}
---
{pageName !== undefined && <div>pageName={pageName}</div>}<br />
{pageindex !== undefined && <div>pageindex={pageindex}</div>}<br />
{pageTitle !== undefined && <div>pageTitle={pageTitle}</div>}<br />

上記の結果、次のように出力されました。

pageindexpageTitle値はundefinedに設定されていることがわかりました。

paramsを複数定義/ファイル名に複数使用

ファイル名に設定するparams値を増やしてみました。

[pagePrefix]-[pageName].astro
---
const { pageindex, pageTitle, pageName, pagePrefix } = Astro.params;
export interface staticPath {
    params: {
        pageName: string,
        pageindex: number,
        pageTitle: string, 
        pagePrefix: string,
    }
}
export async function getStaticPaths() {
    let staticPaths: staticPath[] = [];
    for (let i = 0; i < 10; i++){
        staticPaths.push({
            params: {
                pageindex: i,
                pageTitle: "Post [" + String(i + 1).padStart(2, '0') + "]",
                pageName:  "post-" + String(i + 1).padStart(2, '0'),
                pagePrefix: "test",
            }    
        })
    }
    return staticPaths;
}
---
pageName={pageName}<br />
pageindex={pageindex}<br />
pageTitle={pageTitle}<br />
pagePrefix={pagePrefix}<br />

上記の結果、次のように出力されました。

ファイル名にpageNamepagePrefixが使用されていて、この二つの値が内部から呼び出しが可能な状態になっていました。

検証から推測される挙動

細かい動作状態はパケットを見たわけではないため不明です。あくまで事象から想像できる挙動を推測し図に起こしました。

おそらくastro側でルーティングを作成する際(図の⑤工程)、ルーティング作成時に使われていないparamsは送信されないようになっているのだと考えられます。

ルーティング後のページに値を渡すにはどうすればいい?

props値をgetStaticPaths()の戻り値に指定することで、ルーティング後のページに変数を渡すことができます。

[pageName].astro
---
const { pageName } = Astro.params;
const { pageindex, pageTitle } = Astro.props;
export interface staticPath {
    params: {
        pageName: string | undefined},
    props: {
        pageindex: number | undefined,
        pageTitle: string | undefined,
    }
}
export async function getStaticPaths() {
    let staticPaths: staticPath[] = [];
    for (let i = 0; i < 10; i++){
        staticPaths.push({
            params: {
                pageName:  "post-" + String(i + 1).padStart(2, '0'),
            },
            props: {
                pageindex: i,
                pageTitle: "Post [" + String(i + 1).padStart(2, '0') + "]",
            }    
        })
    }
    return staticPaths;
}
---
{pageName !== undefined && <div>pageName={pageName}</div>}<br />
{pageindex !== undefined && <div>pageindex={pageindex}</div>}<br />
{pageTitle !== undefined && <div>pageTitle={pageTitle}</div>}<br />

上記の結果、次のように出力されました。

参考

https://docs.astro.build/en/core-concepts/routing/#example-dynamic-pages-at-multiple-levels

Discussion