基礎から学ぶJavaScript入門 90日コース | 非同期処理とAPI - Day 64:検索APIアプリ①

JavaScript 90日で身につけるJavaScript
スポンサーリンク
スポンサーリンク

Day 64:検索APIアプリ①

Day 64では、第5フェーズ「非同期処理とAPI」の制作として、ユーザー検索アプリを作ります。今回の機能は、キーワード入力、API検索、結果表示の3つです。Day 59からDay 63までで、fetch() を使ったAPI通信、公開APIからのデータ取得、取得データの画面表示、ローディング処理、エラー処理までを学んできました。今回のDay 64は、それらを単発の練習としてではなく、「1つの小さなアプリ」としてまとめる回です。つまり、ここで初めて「入力 → 通信 → 表示」という、実際の検索アプリらしい流れを完成させます。

初心者の方にとって、このDay 64はかなり重要な節目です。なぜなら、これまでは「決まったURLからデータを取る」練習が中心でしたが、今回は「ユーザーが入力した内容によって取得結果が変わる」という、動的なアプリへ進むからです。これは単なるデータ取得より一歩進んだ考え方です。自分が固定で用意したURLにアクセスするだけでなく、「入力内容を使って検索条件を変える」という発想が必要になります。ここが理解できると、検索アプリ、商品検索、記事検索、メンバー検索など、多くの実用アプリの入口が見えてきます。

ただし、初心者の方はここでいくつかの点で混乱しやすいです。たとえば、「入力したキーワードをどう使うのか」「本当にAPIで検索しているのか、それとも取ったデータをあとで絞り込んでいるのか」「結果が0件のときはどうするのか」「空欄のまま検索したらどうするのか」といった点です。今回のDay 64では、そうしたポイントを1つずつ分解しながら、プログラミング初心者向けに丁寧に整理していきます。なお、今回は学習しやすさを重視し、公開APIから取得したユーザーデータをJavaScript側で絞り込む形で「検索アプリ」の基本構造を学びます。これによって、API取得と検索結果表示の考え方を無理なく理解できます。

まず最初に結論をつかむ

最初に今回の内容を一言でまとめると、ユーザー検索アプリとは「入力欄に入れたキーワードをもとにデータを取得し、その中から条件に合うユーザーを画面へ表示するアプリ」です。

今回の基本の流れは次の通りです。

  • 入力欄にキーワードを入れる
  • 検索ボタンを押す
  • APIからユーザーデータを取得する
  • キーワードに合うデータだけを絞り込む
  • 結果を画面に表示する

初心者の方は、まずこの「入力 → 取得 → 絞り込み → 表示」という流れを一本で理解することが大切です。

今回の検索アプリで学ぶこと

今回のアプリでは、見た目はシンプルですが、実はこれまで学んできた重要な要素がまとめて入っています。

  • 入力欄から値を取得する
  • ボタンクリックイベントを処理する
  • `fetch()` でAPIからデータを取得する
  • `response.json()` でデータを読む
  • 配列データを `filter()` で絞り込む
  • 結果を `forEach()` で画面に表示する
  • 空検索や0件検索への対応を考える
  • 必要ならエラー処理やローディング処理も組み込む

初心者の方は、「検索アプリ」と聞くと新しいことばかりに見えるかもしれませんが、実際にはこれまで学んだ部品を組み合わせる回だと考えると安心しやすいです。

なぜ検索アプリが学習に向いているのか

検索アプリは、初心者の学習題材としてとても優れています。なぜなら、入力・条件分岐・配列操作・非同期処理・画面表示が自然につながるからです。しかも、使う人にも動きがわかりやすく、達成感があります。

たとえば、次のような力が同時に鍛えられます。

  • ユーザー入力を受け取る力
  • データを条件で絞り込む力
  • 結果を見やすく表示する力
  • 入力ミスや0件時の表示を考える力

初心者の方は、検索アプリを通して「機能をつなげてアプリにする感覚」をつかみやすくなります。

まずは完成イメージを持つ

コードに入る前に、どんなアプリを作るのかを言葉で整理しておきます。今回作るユーザー検索アプリは、たとえば次のような動きです。

  • 入力欄に `Leanne` と入れる
  • 検索ボタンを押す
  • APIからユーザー一覧を取得する
  • 名前に `Leanne` を含むユーザーだけを表示する

また、e のような文字を入れれば、その文字を含むユーザーが複数件表示されることもあります。逆に、存在しないキーワードを入れれば0件になります。このように、同じデータでも入力内容によって結果が変わるのが検索アプリの面白いところです。

今回使うAPIについて

今回は、学習用としてわかりやすい公開APIを使います。ユーザー一覧データが取得できるURLは、たとえば次のような形です。

https://jsonplaceholder.typicode.com/users
JavaScript

このURLへアクセスすると、複数のユーザー情報が配列で返ってきます。各ユーザーには、たとえば次のような情報があります。

  • `name`:名前
  • `email`:メールアドレス
  • `phone`:電話番号
  • `company.name`:会社名

初心者の方は、まず「APIから返ってくるのはユーザー1件ではなく、ユーザー配列である」と理解すると、このあとの filter() や forEach() がつながりやすくなります。

検索とは何をしているのか

ここはとても大切です。今回の検索は、API側にキーワードを送って直接検索しているわけではありません。まずユーザー一覧を取得し、そのあとJavaScript側で絞り込んでいます。つまり、今回の検索の正体は「配列の中から条件に合うデータを選ぶこと」です。

そのために使うのが filter() です。

const results = users.filter(function (user) {
  return user.name.includes(keyword);
});
JavaScript

このコードでは、user.name の中に keyword が含まれているユーザーだけを取り出しています。初心者の方は、「検索 = データを探すこと」ではなく、「条件に合う要素だけを残すこと」と考えると理解しやすいです。

ステップ1:HTMLの部品を用意する

まずはアプリに必要なHTMLを用意します。今回は最低限、次の部品が必要です。

  • キーワード入力欄
  • 検索ボタン
  • メッセージ表示エリア
  • 検索結果一覧エリア

基本のHTMLは次のようになります。

<h2>ユーザー検索アプリ</h2>

<input type="text" id="keywordInput" placeholder="名前を入力してください">
<button id="searchButton">検索</button>

<p id="message">キーワードを入力して検索してください。</p>
<ul id="resultList"></ul>

初心者の方は、まず「入力する場所」「押す場所」「結果が出る場所」をはっきり分けておくと、JavaScript側の役割が見えやすくなります。

ステップ2:入力値を取得する

次に、検索ボタンが押されたときに入力欄の値を取得します。

const keywordInput = document.getElementById("keywordInput");
const searchButton = document.getElementById("searchButton");

searchButton.addEventListener("click", function () {
  const keyword = keywordInput.value.trim();
  console.log(keyword);
});
JavaScript

ここでは trim() を使って、前後の空白を除いています。これはとても大事です。たとえば、見た目では文字が入っているようでも、空白だけなら実質的には空入力と同じだからです。

初心者の方は、入力値を受け取ったらまず console.log() で確認する習慣をつけると、あとで原因を見つけやすくなります。

ステップ3:空欄チェックを入れる

検索アプリでは、空欄のまま検索されたときの対策がとても重要です。何も入力されていないなら、意味のある検索にならないからです。

searchButton.addEventListener("click", function () {
  const keyword = keywordInput.value.trim();

  if (keyword === "") {
    message.textContent = "キーワードを入力してください。";
    return;
  }

  console.log(keyword);
});
JavaScript

初心者の方は、検索機能を作るときに「正しい入力がある前提」で進めず、「入力が不十分な場合」を先に考える習慣を持つと堅実です。

ステップ4:APIからユーザー一覧を取得する

次に、検索ボタンクリック時にAPIからユーザー一覧を取得します。

async function searchUsers() {
  const response = await fetch("https://jsonplaceholder.typicode.com/users");
  const users = await response.json();

  console.log(users);
}
JavaScript

これで、ユーザー配列が取得できます。初心者の方は、ここでも一度 console.log(users) を見て、「配列になっていること」「各要素がオブジェクトであること」を確認すると理解しやすいです。

ステップ5:取得したデータを絞り込む

ここから検索らしくなります。取得したユーザー配列を、入力キーワードで絞り込みます。

const results = users.filter(function (user) {
  return user.name.includes(keyword);
});
JavaScript

このコードの意味は、「ユーザー名の中に入力キーワードが含まれているものだけ残す」です。たとえば Le と入力すれば、Leanne Graham のような名前がヒットする可能性があります。

初心者の方は、filter() の中が true なら残り、false なら消える、という動きを意識するとわかりやすいです。

大文字・小文字を気にしない検索にする

ここはかなり大切な改善ポイントです。includes() はそのままだと大文字・小文字を区別します。そのため、leanne と入力すると Leanne が見つからないことがあります。これを防ぐには、両方を小文字にそろえて比較します。

const results = users.filter(function (user) {
  return user.name.toLowerCase().includes(keyword.toLowerCase());
});
JavaScript

この形にすると、入力が Leanne でも leanne でも LEANNE でも一致しやすくなります。初心者の方は、「検索のしやすさは比較方法で変わる」と理解すると、より使いやすいアプリを作れるようになります。

ステップ6:検索結果を画面に表示する

次に、絞り込んだ結果を画面へ表示します。まず表示先を空にしてから、新しい結果を追加します。

resultList.innerHTML = "";

results.forEach(function (user) {
  const li = document.createElement("li");
  li.textContent = user.name;
  resultList.appendChild(li);
});
JavaScript

このコードで、検索条件に合ったユーザー名が一覧表示されます。初心者の方は、ここでも流れを分解すると理解しやすいです。

  • 前回の結果を消す
  • 1件ずつ取り出す
  • `li` を作る
  • ユーザー名を入れる
  • 一覧に追加する

検索結果0件への対応

ここは検索アプリで非常に重要です。検索結果が0件だったときに何も表示しないだけだと、「本当に検索されたのか」「壊れているのか」がわかりにくくなります。そこで、0件用のメッセージを出します。

if (results.length === 0) {
  message.textContent = "該当するユーザーが見つかりませんでした。";
  return;
}
JavaScript

初心者の方は、空データ表示の考え方がここでも大切だと気づけるはずです。Day 54のUI改善ともつながっています。

メッセージ表示の役割を整理する

検索アプリでは、メッセージ表示欄にさまざまな役割があります。

  • 入力を促す
  • 空欄エラーを知らせる
  • 検索中を知らせる
  • 0件を知らせる
  • 検索成功を知らせる
  • 通信失敗を知らせる

つまり、メッセージ欄は単なる文章表示ではなく、「今の状態を案内する場所」です。初心者の方は、検索アプリでは結果一覧だけでなく、こうした補助メッセージも非常に大切だと理解すると、完成度が上がります。

ローディング処理とエラー処理も組み込む

これまで学んだ内容をつなげるために、ローディングとエラー処理も入れます。検索アプリでも外部通信をしている以上、やはり必要です。

  • 検索開始時に「検索中です…」を表示する
  • 通信失敗時にエラーメッセージを表示する
  • 成功でも失敗でも最後にローディングを消す

初心者の方は、検索アプリは単に filter() だけではなく、「入力」「通信」「状態表示」まで含めて完成すると考えると実践的です。

そのまま使える完成テンプレート

ここでは、Day 64の内容をまとめた完成テンプレートを紹介します。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Day 64 ユーザー検索アプリ</title>
  <style>
    /* ローディング表示 */
    #loading {
      display: none;
      color: blue;
      font-weight: bold;
    }

    /* エラーメッセージ用 */
    .error {
      color: red;
    }

    /* 結果リストの余白 */
    li {
      margin-bottom: 8px;
    }
  </style>
</head>
<body>
  <h2>ユーザー検索アプリ</h2>

  <input type="text" id="keywordInput" placeholder="名前を入力してください">
  <button id="searchButton">検索</button>

  <p id="loading">検索中です...</p>
  <p id="message">キーワードを入力して検索してください。</p>
  <ul id="resultList"></ul>

  <script>
    // 必要な要素を取得する
    const keywordInput = document.getElementById("keywordInput");
    const searchButton = document.getElementById("searchButton");
    const loading = document.getElementById("loading");
    const message = document.getElementById("message");
    const resultList = document.getElementById("resultList");

    // ユーザー検索を行う関数
    async function searchUsers() {
      // 入力値を取得する
      const keyword = keywordInput.value.trim();

      // 前回の検索結果を空にする
      resultList.innerHTML = "";

      // メッセージの見た目を初期化する
      message.classList.remove("error");

      // 空欄チェック
      if (keyword === "") {
        message.textContent = "キーワードを入力してください。";
        message.classList.add("error");
        return;
      }

      try {
        // ローディング表示を出す
        loading.style.display = "block";
        message.textContent = "ユーザーを検索中です...";

        // APIからユーザー一覧を取得する
        const response = await fetch("https://jsonplaceholder.typicode.com/users");

        // HTTPエラーなら失敗として扱う
        if (!response.ok) {
          throw new Error("サーバーエラーが発生しました。");
        }

        // JSONデータを読み取る
        const users = await response.json();

        // キーワードを含むユーザーだけに絞り込む
        const results = users.filter(function (user) {
          return user.name.toLowerCase().includes(keyword.toLowerCase());
        });

        // 該当なしの場合
        if (results.length === 0) {
          message.textContent = "該当するユーザーが見つかりませんでした。";
          return;
        }

        // 件数メッセージを表示する
        message.textContent = `${results.length}件のユーザーが見つかりました。`;

        // 検索結果を画面に表示する
        results.forEach(function (user) {
          const li = document.createElement("li");

          // 名前とメールアドレスを表示する
          li.textContent = `${user.name} / ${user.email}`;

          resultList.appendChild(li);
        });
      } catch (error) {
        // エラー時の表示
        message.textContent = "検索に失敗しました。時間をおいて再試行してください。";
        message.classList.add("error");

        // 開発者向けに詳細を出す
        console.log("エラー詳細:", error);
      }

      // ローディング表示を消す
      loading.style.display = "none";
    }

    // ボタンが押されたら検索を実行する
    searchButton.addEventListener("click", function () {
      searchUsers();
    });
  </script>
</body>
</html>

この完成コードの見方

初心者の方は、完成コードを一度に全部理解しようとすると大変です。そのため、次の順番で読むのがおすすめです。

  • HTMLで、入力欄・ボタン・メッセージ欄・結果欄を確認する
  • JavaScriptで、最初に要素取得部分を見る
  • 次に空欄チェックを見る
  • そのあと `fetch()` と `response.json()` を確認する
  • 次に `filter()` で絞り込む部分を見る
  • 最後に `forEach()` で結果表示する部分を見る

このように分けて読むと、コードの役割がかなり見えやすくなります。

特に深掘りしたい重要ポイント

今回、特に大切なのは「検索の本体は filter() である」という点です。初心者の方は、検索アプリという言葉からAPIだけを意識しがちですが、実際には、APIはデータ取得担当であり、検索条件に合うものを選んでいるのはJavaScriptの filter() です。この役割分担が理解できると、今後ほかの検索アプリを作るときにも応用しやすくなります。

また、入力値の前後空白を消す trim()、大文字小文字をそろえる toLowerCase()、0件時のメッセージ表示など、「検索の使いやすさ」は細かい工夫の積み重ねで決まることも重要です。ここまで意識できると、ただ動くだけでなく、実際に使いやすいアプリへ近づきます。

情報セキュリティの観点での注意

検索アプリでは、外部APIから取得したデータを画面へ表示します。そのため、表示に使う値は外部から来たデータであるという意識が大切です。学習段階では信頼できる公開APIを使う前提ですが、それでもまずは textContent ベースで安全に表示する基本を守るのがよいです。また、エラー時に内部情報をそのまま画面へ出しすぎないことも重要です。初心者の方は、「外部データは便利だが、そのまま全面的に信頼しすぎない」という感覚を持つと、安全な開発習慣につながります。

初心者が特に注意したいポイント

Day 64では、次の点を特に意識すると理解が深まりやすいです。

  • 検索アプリは、入力・取得・絞り込み・表示の流れでできています。
  • 空欄チェックは必須です。
  • 検索結果0件のときも、画面でわかるようにすることが大切です。
  • `filter()` が検索の中心です。
  • 大文字小文字をそろえると使いやすい検索になります。
  • 通信エラーやローディング表示も検索アプリの完成度に関わります。

特に重要なのは、「検索結果一覧だけでなく、今の状態を伝えるメッセージも設計の一部」だという点です。

Day 64のゴールを整理する

Day 64では、次のことができるようになっていれば十分です。

  • キーワード入力欄から値を取得できる
  • 公開APIからユーザーデータを取得できる
  • `filter()` を使って検索条件に合うデータだけを取り出せる
  • 検索結果をHTMLへ一覧表示できる
  • 空欄時、0件時、エラー時の表示を適切に分けられる
  • ローディング表示を使って検索中の状態を伝えられる

ここまでできれば、Day 64としてはとても順調です。API通信と配列検索と画面表示が、1つのアプリとしてしっかりつながっています。

まとめ

Day 64では、第5フェーズ「非同期処理とAPI」の制作として、ユーザー検索アプリを作成しました。今回のアプリでは、入力欄にキーワードを入れ、検索ボタンを押し、公開APIから取得したユーザーデータの中から条件に合うものだけを絞り込んで画面へ表示する、という流れを学びました。技術的には、入力値取得、fetch()、response.json()、filter()、forEach()、結果表示、空欄チェック、0件表示、ローディング表示、エラー処理といった、これまで学んだ要素が1本につながっています。

特に大切なのは、検索の本体が filter() にあること、そして使いやすい検索アプリにするには、空欄・0件・エラー・読み込み中といった状態まで含めて設計する必要があることです。こうした考え方が身につくと、単にデータを表示するだけでなく、「ユーザーが使いやすいアプリ」を作る感覚が育っていきます。

次に進む前に、今回のテンプレートを実際に動かし、名前ではなくメールアドレスで検索するように変えてみたり、会社名でも検索できるようにしたりするのがおすすめです。そして、「入力値がどこで使われ、どの段階で結果が絞り込まれているのか」を自分の言葉で説明できるようになると、Day 64の理解がかなり深まっています。

タイトルとURLをコピーしました