JavaScript | 1 日 120 分 × 7 日アプリ学習:API通信アプリ(NewsAPI.org)

APP JavaScript
スポンサーリンク

6日目のゴールと今日やること

6日目のテーマは
「fetch・async/await・エラーハンドリングの“型”をそのままに、検索機能を“より賢く・柔軟に”する」
ことです。

ここまでであなたはすでに、

  • キーワード検索
  • 期間・並び順・ソース絞り込み
  • ページネーション
  • お気に入り
  • 最近見た記事
  • 状態管理の整理

といった“ニュースアプリの基礎〜中級”を習得しました。

6日目はここに、

  • 複数キーワード検索(AND / OR)
  • 検索条件プリセット(よく使う条件をワンタッチ)
  • API 通信の共通化(fetch のロジックを一箇所にまとめる)
  • エラーハンドリングの強化(どこで失敗したかを明確に)

を加えて、「検索の幅が広がるニュースアプリ」に進化させます。


複数キーワード検索を実装する

NewsAPI の q は「スペースで区切ると AND 検索」

NewsAPI の検索仕様はこうです。

q=apple microsoft
→ apple AND microsoft の記事

q="apple OR microsoft"
→ OR 検索

つまり、
「スペース区切りで AND」
「OR を自分で書けば OR」
という仕組みです。

UI に複数キーワード入力欄を追加する

<input id="keywordInput" placeholder="キーワード (例: JavaScript AI)" />

ユーザーがスペース区切りで入力すれば、
そのまま AND 検索になります。

OR 検索をサポートする

ユーザーが「,(カンマ)」で区切った場合は OR として扱う、
というルールを作ると便利です。

例:

JavaScript, Python
→ JavaScript OR Python

キーワードを整形する関数を作る

function buildQuery(keyword) {
  if (keyword.includes(",")) {
    const parts = keyword.split(",").map((p) => p.trim());
    return parts.join(" OR ");
  }
  return keyword;
}
JavaScript

buildUrl に組み込む

function buildUrl(state) {
  const params = new URLSearchParams({
    q: buildQuery(state.keyword),
    apiKey: API_KEY,
    language: "ja",
    sortBy: state.sortBy,
    page: String(state.page),
    pageSize: String(state.pageSize)
  });

  if (state.from) params.set("from", state.from);
  if (state.to) params.set("to", state.to);
  if (state.source) params.set("sources", state.source);

  return `${baseUrl}?${params.toString()}`;
}
JavaScript

深掘り:複数キーワード検索は「文字列処理 × fetch」の応用

ここで重要なのは、

  • fetch の書き方は変わらない
  • async/await も変わらない
  • 変わるのは「q の作り方」だけ

という点です。

API 通信の本質はそのままに、
入力(キーワード)の加工だけで検索の幅が広がる
ということを体験してほしい。


検索条件プリセットを実装する

プリセットとは?

「よく使う検索条件をボタン一つで呼び出す」仕組みです。

例:

  • テクノロジー最新ニュース
  • 日本の政治ニュース
  • 海外のビジネスニュース

毎回キーワードやソースを入力するのは面倒なので、
プリセットを作ると一気に便利になります。

UI にプリセットボタンを追加する

<button class="preset" data-keyword="AI, Technology" data-sort="publishedAt">
  最新テックニュース
</button>

<button class="preset" data-keyword="Japan politics" data-sort="relevancy">
  日本の政治ニュース
</button>

プリセットを押したときの処理

const presetButtons = document.querySelectorAll(".preset");

presetButtons.forEach((btn) => {
  btn.addEventListener("click", () => {
    const keyword = btn.dataset.keyword;
    const sortBy = btn.dataset.sort;

    updateState({
      keyword,
      sortBy,
      page: 1
    });

    keywordInput.value = keyword;
    sortSelect.value = sortBy;

    fetchNewsWithCurrentState();
  });
});
JavaScript

深掘り:プリセットは「状態をまとめて更新する」練習

プリセットは、

  • 状態をまとめて変更する
  • UI に反映する
  • fetch を呼ぶ

という 3 ステップで構成されています。

これは「状態管理の理解」を深める最高の練習です。


API 通信を共通化する(中級者の必須スキル)

fetch のロジックを一箇所にまとめる

今までは fetchNewsWithCurrentState の中で fetch をしていましたが、
6日目では「API 通信専用の関数」を作ります。

async function requestNews(url) {
  const response = await fetch(url);

  if (!response.ok) {
    throw new Error(`HTTPエラー(${response.status})`);
  }

  const data = await response.json();

  if (data.status === "error") {
    throw new Error(data.message);
  }

  return data;
}
JavaScript

fetchNewsWithCurrentState をシンプルにする

async function fetchNewsWithCurrentState() {
  if (state.isLoading) return;

  startLoading();
  showLoadingStatus();
  renderLoadingSkeleton();

  try {
    const url = buildUrl(state);
    const data = await requestNews(url);

    showStatus(`ニュース取得成功(ページ ${state.page})`);
    renderArticles(data);
    updatePaginationInfo(data);
    addHistory(state.keyword);

  } catch (error) {
    showError(`取得に失敗しました:${error.message}`);
  } finally {
    endLoading();
  }
}
JavaScript

深掘り:fetch を分離すると「再利用性」が爆上がりする

requestNews は、

  • ページネーション
  • プリセット
  • 最近見た記事
  • お気に入り
  • ソース絞り込み

どこからでも使える共通関数になります。

これは中級者が必ず身につけるべき設計です。


エラーハンドリングを強化する

失敗した場所を明確にする

複数キーワード検索やプリセットが増えると、
「どこで失敗したのか」がわかりにくくなります。

そこで、エラーに“文脈”を付けます。

function handleError(error, context) {
  if (context) {
    showError(`${context}${error.message}`);
  } else {
    showError(error.message);
  }
}
JavaScript

fetchNewsWithCurrentState の catch を改善

} catch (error) {
  handleError(error, `ページ ${state.page} の取得に失敗`);
}
JavaScript

深掘り:エラーは「ユーザーに伝わる形」に整える

技術的なエラーをそのまま出すのではなく、
「何をしようとして失敗したのか」
を添えることで、ユーザーの理解が深まります。


6日目のまとめ

今日やったことを整理すると、こうなります。

  • fetch・async/await・エラーハンドリングの「型」はそのまま
  • 複数キーワード検索(AND / OR)を実装
  • 検索条件プリセットで操作性アップ
  • API 通信を requestNews に共通化
  • エラーハンドリングを handleError で統一
  • 状態管理の理解がさらに深まる

どれも「新しい文法」ではなく、
“状態管理 × 入力加工 × fetch の再利用”
の組み合わせです。


今日いちばん深く理解してほしいこと

6日目の本質は、

「API 通信の型はもう完成している。
アプリの賢さは“入力の加工”と“状態管理”で決まる」

ということです。

複数キーワード
プリセット
ソース絞り込み
ページ番号
お気に入り
最近見た記事

これらはすべて「状態」です。

状態を整理し、
fetch のロジックを共通化し、
UI に反映する。

この流れを理解できたあなたは、
もう “API を使ったアプリを設計できる人” の領域にいます。

次の 7 日目では、
このニュースアプリを「完成版」としてまとめ、
ローカルストレージ保存や UI の最終調整を行い、
中級編の集大成に仕上げていきます。

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