JavaScript | 1 日 120 分 × 7 日アプリ学習:検索 & ソート機能付き一覧

APP JavaScript
スポンサーリンク

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

2日目のテーマは
「検索・ソート・フィルタ機能を“実際に使える UI とロジック”として組み立てる」
ことです。

1日目では map / filter / sort の基本と、
リアルタイム検索・ソート・複合条件フィルタの“ロジック部分”を学びました。

2日目では、それらを UI(入力欄・ボタン)と結びつけて、実際に動く一覧アプリにする ところまで進めます。

今日のポイントは次の 3 つ。

  • 状態管理(state)を導入して、検索・ソート・フィルタを一元管理
  • UI 操作(検索欄・ソートボタン・年齢スライダー)とロジックをつなぐ
  • map / filter / sort を組み合わせて「処理の流れ」を作る

初心者がつまずきやすい「UI とロジックの分離」を丁寧に解説します。


アプリのデータと UI を整理する

今日扱うデータ(例)

const users = [
  { id: 1, name: "Alice", age: 24 },
  { id: 2, name: "Bob", age: 30 },
  { id: 3, name: "Charlie", age: 28 },
  { id: 4, name: "David", age: 35 },
  { id: 5, name: "Eve", age: 22 }
];
JavaScript

UI のイメージ

<input id="searchInput" placeholder="名前で検索" />

<button id="sortAsc">年齢 昇順</button>
<button id="sortDesc">年齢 降順</button>

<input id="minAge" type="number" placeholder="最小年齢" />
<input id="maxAge" type="number" placeholder="最大年齢" />

<div id="list"></div>

状態管理(state)を導入する

なぜ state が必要なのか

検索 → ソート → フィルタ
のように複数の処理が重なると、

  • 「今どんな検索キーワード?」
  • 「今ソートは昇順?降順?」
  • 「年齢フィルタは何歳〜何歳?」

といった情報を一箇所で管理したくなります。

そこで state を導入します。

state の基本形

const state = {
  keyword: "",
  sort: "none", // "asc" or "desc"
  minAge: null,
  maxAge: null
};
JavaScript

状態を更新する関数

function updateState(updates) {
  Object.assign(state, updates);
  applyFilters();
}
JavaScript

updateState を呼ぶだけで、
検索・ソート・フィルタが全部反映されるようにします。


applyFilters で「処理の流れ」を作る

1日目の学びを組み合わせる

function applyFilters() {
  let result = [...users]; // 非破壊コピー

  if (state.keyword) {
    const lower = state.keyword.toLowerCase();
    result = result.filter(user =>
      user.name.toLowerCase().includes(lower)
    );
  }

  if (state.minAge !== null) {
    result = result.filter(user => user.age >= state.minAge);
  }

  if (state.maxAge !== null) {
    result = result.filter(user => user.age <= state.maxAge);
  }

  if (state.sort === "asc") {
    result = [...result].sort((a, b) => a.age - b.age);
  }

  if (state.sort === "desc") {
    result = [...result].sort((a, b) => b.age - a.age);
  }

  renderList(result);
}
JavaScript

深掘りポイント

ここが今日の最重要ポイントです。

  • filter → filter → sort の順で処理
  • すべて非破壊(元の users は壊さない)
  • state の内容に応じて処理が変わる
  • 最後に renderList で表示

これが「検索・ソート・フィルタの統合ロジック」です。


リアルタイム検索を state とつなぐ

searchInput.addEventListener("input", () => {
  updateState({ keyword: searchInput.value });
});
JavaScript

深掘りポイント

input イベントは「文字が入力されるたびに発火」します。
updateState → applyFilters → renderList
という流れが自動で走ります。


昇順 / 降順ソートボタンを作る

sortAsc.addEventListener("click", () => {
  updateState({ sort: "asc" });
});

sortDesc.addEventListener("click", () => {
  updateState({ sort: "desc" });
});
JavaScript

深掘りポイント

sort は state.sort に文字列で保存します。

  • “asc” → 昇順
  • “desc” → 降順

applyFilters の中で sort の値を見て処理を切り替えます。


年齢フィルタ(複合条件)を UI とつなぐ

入力欄のイベント

minAge.addEventListener("input", () => {
  const value = Number(minAge.value);
  updateState({ minAge: Number.isFinite(value) ? value : null });
});

maxAge.addEventListener("input", () => {
  const value = Number(maxAge.value);
  updateState({ maxAge: Number.isFinite(value) ? value : null });
});
JavaScript

深掘りポイント

  • 数値でない場合は null に戻す
  • null のときはフィルタを適用しない
  • filter の条件を組み合わせるだけで複合条件になる

filter は「条件を増やすほど絞り込まれる」ので、
複合条件フィルタと相性が抜群です。


一覧表示の render 関数

function renderList(arr) {
  if (!arr.length) {
    listDiv.textContent = "該当するユーザーはいません。";
    return;
  }

  let html = "";
  arr.forEach(user => {
    html += `<p>${user.name}${user.age}歳)</p>`;
  });

  listDiv.innerHTML = html;
}
JavaScript

深掘りポイント

render は「表示にだけ責任を持つ」ようにします。
ロジックと UI を分けることで、コードが読みやすくなります。


2日目のまとめ

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

  • state を導入して検索・ソート・フィルタを一元管理
  • updateState → applyFilters → renderList の流れを作った
  • filter を組み合わせて複合条件フィルタを実装
  • sort を非破壊で実装(スプレッド構文)
  • リアルタイム検索を input イベントで実装
  • ソートボタン・年齢フィルタを UI とつなげた

どれも中級者に必須のスキルです。


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

2日目の本質は、

「検索・ソート・フィルタは、state を中心に map / filter / sort を組み合わせることで“ひとつの流れ”になる」

ということです。

検索
→ 年齢フィルタ
→ ソート
→ 表示

この流れを applyFilters にまとめることで、
アプリ全体がスッキリ整理されます。

3日目では、この一覧アプリに

  • タグフィルタ
  • 複数条件の OR / AND
  • ページネーション
  • UI の改善

などを加えて、さらに“実務レベルの一覧アプリ”に育てていきます。

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