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

APP JavaScript
スポンサーリンク

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

7日目のテーマは
「NewsAPI を使ったニュースアプリを“中級レベルの完成形”に仕上げる」
ことです。

ここまでであなたは、

  • fetch と async/await の基本
  • HTTP エラー / API エラー / 通信エラーの 3 段階ハンドリング
  • ページネーション
  • ソース絞り込み
  • お気に入り
  • 最近見た記事
  • 検索履歴
  • 状態管理の整理

といった“API 通信アプリの中核”を習得しました。

7日目は、これらを 「アプリとして筋の通った構造にまとめる」 ことに集中します。

今日のポイントは次の 4 つです。

  • ローカルストレージ保存(履歴・お気に入り・最近見た記事)
  • UI の最終調整(読みやすさ・操作性)
  • fetch / async/await / エラーハンドリングの最終フォーム
  • コードのリファクタリング(役割ごとに整理)

ローカルストレージで「データが残るアプリ」にする

なぜローカルストレージが必要なのか

今までの履歴・お気に入り・最近見た記事は、
ページをリロードすると消えてしまいました。

ユーザーが毎日使うアプリにするには、
データが残ること が必須です。

そこで使うのが localStorage です。

localStorage の基本

localStorage は「文字列しか保存できない」ため、
オブジェクトや配列は JSON に変換します。

保存:

localStorage.setItem("favorites", JSON.stringify(favorites));
JavaScript

読み込み:

const saved = JSON.parse(localStorage.getItem("favorites") || "[]");
JavaScript

お気に入りを保存する

お気に入り追加時に保存します。

function addFavorite(article) {
  const exists = favorites.some((fav) => fav.url === article.url);
  if (exists) return;

  favorites.push(article);
  localStorage.setItem("favorites", JSON.stringify(favorites));
  renderFavorites();
}
JavaScript

履歴も保存する

function addHistory(keyword) {
  if (history.includes(keyword)) return;

  history.unshift(keyword);
  if (history.length > 5) history.pop();

  localStorage.setItem("history", JSON.stringify(history));
  renderHistory();
}
JavaScript

最近見た記事も保存する

function addRecent(article) {
  const exists = recentArticles.some((a) => a.url === article.url);
  if (!exists) {
    recentArticles.unshift(article);
    if (recentArticles.length > 5) recentArticles.pop();
  }

  localStorage.setItem("recent", JSON.stringify(recentArticles));
  renderRecent();
}
JavaScript

初期化時に読み込む

アプリ起動時に一度だけ読み込みます。

function loadSavedData() {
  favorites = JSON.parse(localStorage.getItem("favorites") || "[]");
  history = JSON.parse(localStorage.getItem("history") || "[]");
  recentArticles = JSON.parse(localStorage.getItem("recent") || "[]");

  renderFavorites();
  renderHistory();
  renderRecent();
}

loadSavedData();
JavaScript

深掘り:状態を「保存する」ことでアプリが一気に“本物”になる

ローカルストレージを使うと、

  • ページを閉じてもデータが残る
  • 再読み込みしても履歴が表示される
  • お気に入りが永続化される

という“アプリらしさ”が一気に増します。

fetch や async/await の知識をそのまま活かしつつ、
「状態を保存する」という新しい視点 を得ることが今日の大きな成長ポイントです。


UI の最終調整:ユーザーが迷わない画面にする

ステータス表示を「色 × メッセージ」で統一する

7日目では、ステータス表示を完全にパターン化します。

function setStatus(message, type) {
  statusDiv.textContent = message;
  statusDiv.className = "status " + type;
}
JavaScript

CSS で色を統一します。

.status.loading { color: #555; }
.status.success { color: #0a0; }
.status.error { color: #c00; }

これにより、

  • ローディング
  • 成功
  • エラー

が視覚的に統一され、ユーザーが迷わなくなります。

スケルトン表示を改善する

読み込み中に「空白」ではなく、
「ここに記事が並ぶよ」というダミー UI を表示します。

function renderLoadingSkeleton() {
  let html = "";
  for (let i = 0; i < 3; i++) {
    html += `
      <div class="article skeleton">
        <h3>読み込み中...</h3>
        <p>説明文を読み込み中です…</p>
        <p>提供元:読み込み中…</p>
      </div>
    `;
  }
  resultDiv.innerHTML = html;
}
JavaScript

ユーザー体験が大きく向上します。


fetch / async/await / エラーハンドリングの「最終フォーム」

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

状態を使ってニュースを取得する関数

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 の「型」が完全に身についた証拠

この構造が書けるようになれば、
どんな API でも同じように扱えます。

  • fetch
  • await
  • response.ok
  • data.status
  • try / catch / finally

この 5 つが揃えば、
API 通信は怖くありません。


コードのリファクタリング:役割ごとに整理する

役割を 4 つに分ける

アプリのコードは、次の 4 つに分けると読みやすくなります。

1. 状態管理(state)

検索条件・ページ番号・お気に入り・履歴など。

2. API 通信(requestNews)

fetch と async/await のロジック。

3. UI 更新(renderArticles / renderHistory / renderFavorites)

画面に表示する部分。

4. イベント処理(ボタンのクリックなど)

ユーザー操作を受け取る部分。

この 4 つを意識すると、
コードが迷子にならなくなります。


7日目のまとめ

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

  • ローカルストレージで履歴・お気に入り・最近見た記事を保存
  • UI を統一して「迷わない画面」にする
  • fetch / async/await / エラーハンドリングの最終フォームを完成
  • API 通信・状態管理・UI 更新・イベント処理を分離して整理

どれも「新しい文法」ではなく、
“状態管理 × UI × fetch の型”
の組み合わせです。


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

7日目の本質は、

「API 通信の型はもう完全に身についた。
これからは“アプリ全体の設計”が重要になる」

ということです。

あなたはもう、
「API を叩ける人」ではなく、
“API を使ったアプリを設計できる人”
の領域にいます。

この 7 日間で身につけた型は、
天気 API でも、ニュース API でも、
どんな REST API でもそのまま使えます。

次は、あなたが作りたいアプリを一緒に設計していこう。

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