2.1 題材設定 — ToDo リストの仕様
この Part では React を一切使わず、素の JavaScript で小さなアプリを作っていきます。題材は ToDo リスト です。「タスクを足す・消す・完了にする・種類ごとに絞り込む」という、どこの案件でも一度は書く形の UI ですね。
地味な題材に見えるかもしれません。でも、ToDo リストは 状態と DOM の同期 という一番厄介な問題を最短で見せてくれる、ちょうどいい大きさの題材です。ここで手を動かして積み上げる「面倒」のリストは、Part 3 以降で React のコードを読むときに「これは React が肩代わりしている仕事だ」という視点に変わります。
2.1.1 機能仕様
作るアプリの機能は次の 5 つです。これ以上は広げません。
- タスク追加 — テキスト入力にタスク名を打ち、Enter またはボタンで追加
- タスク削除 — 各タスク行の削除ボタンを押すと消える
- 完了チェック — 各タスク行のチェックボックスで、完了・未完了を切り替え
- フィルタ — 「all / active / completed」の 3 つから 1 つを選ぶと、表示するタスクがその条件で絞り込まれる
- 件数表示 — 未完了タスクの件数を画面下部に表示
完成形の見た目は次のようなイメージです。どこかで見たことがある形だと思います。
図 2.1.1 ToDo リストの完成イメージ
2.1.2 データ構造
画面に出るもののうち、ユーザー操作で変わる情報(=状態)は 2 つだけです。
- タスクの配列
- 選ばれているフィルタ
タスク 1 件を表すオブジェクトはこんな形にします。
{
id: 1, // タスクごとに一意な数値
text: "牛乳を買う", // 表示するテキスト
completed: false, // 完了フラグ
}アプリ全体の状態は、次の 2 つの変数にまとめます。
let todos = []; // { id, text, completed } の配列
let filter = "all"; // "all" | "active" | "completed"id はタスクごとに重複しない値です。配列内の位置(index)で識別すると、並び替えや削除で番号がずれて事故が起きやすいので、別に一意な番号を持たせます。ここでは単純に 1 からの連番で十分です。
図 2.1.2 状態と画面の関係
「状態 → 画面」の向きは、理屈のうえでは一方通行です。ユーザー操作で状態を書き換え、それを元に画面を作り直せば、画面と状態はずれないはず。Part 2 では、この理屈が 素の JavaScript では素直に書けない ことを、手を動かしながら確かめていきます。
2.1.3 なぜ ToDo リストか
案件で React を使う画面の多くは、次の要素の組み合わせでできています。
- リストの表示 — API から取ってきたデータを並べる
- 要素の追加・削除・編集 — ユーザー操作で配列が増減する
- 絞り込み・並び替え — 同じデータから見える形を切り替える
- 入力フォーム — ユーザーからの文字入力を受けて状態に反映する
ToDo リストはこの 4 つをすべて含みます。規模が小さいので、1 ファイルで完結させても、UI 構築で出会う操作の大半が登場します。「小さすぎて現実味がない」と思われがちですが、状態と DOM の同期 という最も厄介な問題を最短距離で露出させられる、良い題材なのです。
図 2.1.3 ToDo に含まれる UI 要素の種類
2.1.4 この Part の動かし方
これから書くコードはすべて、ブラウザだけで動きます。Node.js や npm は使いません。手元で試すには、任意のディレクトリに index.html を 1 つ作り、そのファイルをブラウザで開くだけで動作します。
# 動かし方(参考)
# 1. 任意のディレクトリに index.html を作る
# 2. ファイルを保存した状態で、ブラウザのアドレスバーに file:// のパスを打つ
# もしくはファイルをダブルクリックする章ごとに提示するコードは、特に断りがない限り index.html の中身を全面的に書き換える前提です。
次章から、まずは最も単純な「全部作り直す」方式で実装してみましょう。ここでは動くことを最優先にします。