2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【個人開発】TypeScript で外部 API を使ってブログを取得するアプリをつくる

Posted at

はじめに

JISOU というコミュニティで React + TypeScript + react router v7 の勉強をしています。3 月まで取り組んでいたアプリは、外部 API を使ってブログを取得します。

image.png

工夫してみたところ

課題では Qiita API と microCMS API を使ってブログを取得して表示します。記事の取得が楽しかったので工夫してみたところは

  • ローディング画面の表示
  • コンポーネントはひとつで異なる API のレスポンスを表示できるようにした
  • 複数 API をひとつの loader で実現

です。

ローディング画面の表示

課題では必須ではありませんが、Suspense の対応をしました。Suspense を使ったローディングは素敵な仕組みだと思います。loader では { qiitaItems: qiita.fetchItems() } として Promise が返ってくるようにしています。

export function fetchItems() {
  return new Promise<Article[]>((resolve, reject) => {
    ...
  })
}
export async function loader() {
  return { qiitaItems: qiita.fetchItems() }
}

export default function individuals() {
  let { qiitaItems } = useLoaderData<typeof loader>();

  return (
    <div className="w-full px-20 py-20">
      <div className="flex justify-between">
        <h2 className="text-3xl mb-10">個人記事一覧</h2>
      </div>

      <Suspense fallback={<Loading />}>
        <ArticleList articlesData={qiitaItems} />
      </Suspense>
    </div>
  );
}

その他、Suspense を楽しんでる記事はこちら。

React Router v7 を remix よくわからんエンジニアが遊んでみた

コンポーネントはひとつで異なる API のレスポンスを表示できるようにした

Qiita API と microCMS API のレスポンスに型はそれぞれ用意しました。ただ、同じカードでサムネイルを表示したかったので(過度に抽象化しない程度に)Article クラスをつくり表示するようにしました。Article クラスは次のように resolve の前処理でインスタンスを作るようにしています。

export function fetchContent(contentId: string) {
  ...
  
  return new Promise<Article>((resolve, reject) => {
    client.get({ endpoint: 'blogs', contentId: contentId })
      .then((response: Content) => {
        return response
      })
      .then(data => {
        setTimeout(() => { // ローディングを表示したかったのでやや冗長
          const article = new Article(
            data.id,
            data.title,
            `blogs/${data.id}`,
            data.eyecatch.url,
            data.publishedAt
          )

          resolve(article);
        }, 500); 
      })
      .catch(error => {
        reject(error)
      })
  })
}

複数 API をひとつの loader で実現

loader はフレームワークではデータフェッチのための特別なエントリーポイントです。チュートリアルでよくあるのはひとつの API にアクセスして表示する例が多いですが、複数 API からデータフェッチするのはなかったので苦労しました。気付いたらなんてことはないのですが、ひとつのオブジェクトでレスポンス返すと実現できます。

export async function loader() {
  return { qiitaItems: qiita.fetchItems(), microcmsItems: microcms.fetchContents() }
}
Promise ではなく結果を取得が完了したあとであれば `Promise.all` を使います。

次に向けて

この課題を通して次のことが出来るようになりました。

  • react router v7 のルーティング
  • loader を使った API を使ったデータフェッチ
  • Suspense を使ったローディング

次は無限スクロールにチャレンジしてみたいですね。

JISOUのメンバー募集中!

プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか?
興味のある方は、ぜひホームページをのぞいてみてください!
▼▼▼

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?