外部のコレクションから個々のページをレンダリングする方法


先日この記事をA first look at Astroに書きました.
この記事は、アストロのコレクション機能をショーケースし、しばらくの間アストロとの作業中.
私はコレクションから個々のページを作成する方法を明確に文書化されていないことに気づいた.
それで、私はこれを行って、プロセスを文書化することに決めました.
今日は何を学びますか
外部API からの
  • ユニークな個々のページ
    初期データ・セット
  • より多くのデータを有する
  • 個体ページ
    これらのページ
  • にリンクしている

  • あなたが沿って続くならば、あなたはGitHubから出発コードをダウンロードすることができます.

    Note: Important information regarding the current API state


    この記事を研究している間、私は、Astroが各ページの最初のクエリーをループすると結論しました.これによりAPIはレート制限に使用されました.
    執筆の時点(2021年7月)アストロは、このための修正プログラムに取り組んでいます.
    this PR on GitHub .

    個々のコレクションページの作成
    アストロについてのクールな部分は、私たちは動的にページをロードする1つのファイルを使用することができることを意味するワイルドカードページのセットアップを提供することです!
    この方法は、$(ドル記号)でページを修正することです.
    これは動的なページを作成します.
    APIエンドポイントからトップアニメ番組を掲載しているインデックスページをすでに持っているので、そのショーのためにすべてのエピソードをロードするために、各々のショーのために単身のページを作りましょう.
    ページフォルダで、$show.astroという名前のファイルを作成します.
    フロントエンドの部分(---節)では、このページのコレクションの動作を定義できます.
    我々がする必要がある最初のことは、これがアストロ収集であるということです.
    ---
    const { collection } = Astro.props;
    ---
    
    その後、動的にコレクションを作成することができますcreateCollection関数を呼び出すことができます.
    --------
    const { collection } = Astro.props;
    
    export async function createCollection() {
        // TODO
    }
    --------
    
    このCreateCollection関数は、いくつかの便利なオプションを保持する戻り値が付属しています.
    しかし、私たちがそれらに到達する前に、我々はベースコレクションを定義する必要があります.この場合、ホームページで使用したコレクションを使用します.
    次のコードをコレクション内に配置し、結果を少しループできます.
    このアプローチについてかなり冷静であることは、2つのトップレベルが待つということです.
    export async function createCollection() {
      const remoteData = await fetch('https://kitsu.io/api/edge/anime?sort=-averageRating');
      const remoteJson = await remoteData.json();
      const allData = remoteJson.data;
    
      return {
        // TODO
      };
    }
    
    上記のコードで、コレクションは現在、すべてのショーの配列を含む変数allDataを持っていることを示します.
    最初に返す関数で定義する必要があるのはroutesです.ルートは、このコレクションタイプのルートの合計コレクションを定義します.
    return {
      routes: allData.map((show, i) => {
        const params = {name: show.attributes.canonicalTitle, index: show.id};
        return params;
      }),
    };
    
    私たちはそれぞれのデータオブジェクトをマップして、ショーとIDの名前を含む各ルートのためにparamsを返します.
    それから、我々は各々のルートの最終的なURLであるpermalinkを定義することができます.
    permalink: ({ params }) => `/show/${params.index}`,
    
    これは以下のようなpermalinkを与えるでしょう.
    次に、ページあたりの実際のデータを返す必要があります.これにより、データオプションを返すことでこれを行うことができます.
    async data({ params }) {
        const show = allData.filter(show => show.id == params.index);
        const episodes = await fetch(`https://kitsu.io/api/edge/episodes?filter[mediaId]=${params.index}}`).then(response => response.json());
        show[0] = {...show[0], ...{episodes: episodes.data}};
        return show;
    },
    
    ここで起こるのは、各ページに対して、このデータメソッドがそのルートのためのParamsを使用して呼び出されることです.
    次に、単一のオブジェクトを返すために、IDに基づいてショーをフィルターします.
    我々のケースでは、我々はこのショーのエピソードのリストである余分な情報を取得したい!
    そして、最後に、我々はエピソード配列でショーをマージして、それを返します.
    今、データオブジェクトはフロントエンドに必要なすべてのデータを持つでしょう.

    Note: The return of the data must always be an array!


    最後にPageSizeを設定できます.この場合、無限大の型を使用します.
    pageSize: Infinity,
    
    HTML部分の先頭に進みましょう.このコードがまだ上記の関数と同じファイルにあることに注意してください.
    <html lang="en">
      <head>
        <meta charset="UTF-8" />
        <meta name="viewport" content="width=device-width, initial-scale=1" />
        <title>Anime show: {collection.params?.name}</title>
        <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
        <link rel="stylesheet" href="/style/global.css" />
        <link rel="stylesheet" href="/style/home.css" />
        <style lang="scss">
          .container {
            margin: 4rem;
            display: grid;
            @media (max-width: 650px) {
              margin: 2rem;
            }
          }
          a,
          p {
            margin-bottom: 0.5rem;
          }
          h1 {
            margin-bottom: 1rem;
          }
        </style>
      </head>
      <body>
        <div class="container">
          <a href="/">&larr; Go back</a>
          <h1>{collection.params?.name}</h1>
          <p>These are all episodes for this show:</p>
          <ul class="list">
            {collection.data[0]?.episodes.map((item) =>
            <li>{item.attributes.number} - {item.attributes.canonicalTitle}</li>
            )}
          </ul>
        </div>
      </body>
    </html>
    
    ここでは、このコレクションのデータ属性を使用して、基本的なスタイルとショーケースのショーのタイトルを追加します.
    その後、各エピソードの項目をループし、この特定のショーのエピソードのリストをレンダリングします.

    これらの個々のページへのリンク
    上で述べたように、これらのページはPermalinkのようなshow.idを得るので、我々は既存のホームページレイアウトでそれを活用することができます.
    しかし、カードコンポーネントとしてレンダリングするので、show/4333ファイルを開きましょう.リンクする必要があるので、カードの小道具にIDを追加します.
    --------
    export interface Props {
      id: number;
      title: string;
      image: string;
      episodes: number;
      score: float;
      href: string
    }
    
    const { title, image, episodes, score, href, id  } = Astro.props;
    --------
    
    そして今、カードにリンクを追加することができます.
    <a href={`/show/${id}`}>Read more &rarr;</a>
    
    このIDを---ファイルのカードに渡す必要があります.
    <Card id="{item.id}" ... />
    
    それを行うと、我々は現在、我々のホームページ上の各ショーの個々のページを開くことができます!
    そして、涼しい部分は、一旦我々が我々のサイトを構築するならば、彼らはすべて別々のファイルとしてランタイムでつくられます.
    この例のページで静的出力を試すことができます.
    Anime Astro website
    あなたが今日のために完全なコードを見たいならば、このGitHub repoまで頭を越えてください.

    読んでいただきありがとうございます、接続しましょう!
    私のブログを読んでくれてありがとう.私の電子メール会報を購読して、Facebook