この課題のねらい
ここはいよいよ「コードを書く前に、頭と手で設計する」練習です。
いきなりエディタを開かずに、紙とペンで画面構成・コンポーネント・state を考えられるようになると、
バグも迷いも一気に減ります。
ゴールは、「自分のアプリの設計図を、言葉と簡単な図で説明できること」です。
例題として作るアプリを決める
例:学習ログアプリを題材にする
ここでは具体例として、「学習ログアプリ」を題材にします。
毎日の学習内容と時間を記録して、一覧で見返せるシンプルなアプリを想像してください。
画面としては、次のようなものを用意します。
トップページ(学習ログ一覧+新規追加フォーム)
詳細ページ(1件分の学習ログの詳細)
この例を使って、「紙に書く設計」を順番にやっていきます。
必須課題① 画面構成を紙に書く
画面を「箱」と「ラベル」で描く
紙に、まずはトップページの構成をざっくり描きます。
きれいじゃなくていいので、四角と文字だけで十分です。
上部に「ヘッダー(アプリ名+ナビ)」と書いた箱
その下に「学習ログ追加フォーム」と書いた箱
さらにその下に「学習ログ一覧」と書いた大きめの箱
テキストで表すと、こんなイメージです。
[ ヘッダー:学習ログアプリ | 今日の記録 | 設定 ]
[ 学習ログ追加フォーム ]
- 日付入力
- 学習内容入力
- 学習時間入力
- 追加ボタン
[ 学習ログ一覧 ]
- 1件ずつカード表示
- 日付 / 内容 / 時間 / 詳細ボタン
詳細ページも同じように描きます。
[ ヘッダー:学習ログアプリ ]
[ 学習ログ詳細 ]
- 日付
- 学習内容
- 学習時間
- メモ
- 戻るボタン
ここで大事なのは、「どんな情報がどこに表示されるか」を、
コード抜きでイメージできるようにすることです。
必須課題② コンポーネント分割案を作る
画面の箱をそのままコンポーネント候補にする
さっき紙に描いた箱を、そのままコンポーネント名にしていきます。
トップページなら、こんな分割が考えられます。
ページ全体:LearningLogPage
ヘッダー:AppHeader
学習ログ追加フォーム:LearningLogForm
学習ログ一覧:LearningLogList
学習ログ1件分のカード:LearningLogItem
テキストで構造を書くと、こうなります。
LearningLogPage
├─ AppHeader
├─ LearningLogForm
└─ LearningLogList
└─ LearningLogItem(複数)
詳細ページも同じように分けられます。
LearningLogDetailPage
├─ AppHeader
└─ LearningLogDetail
ここで意識してほしいのは、「役割ごとに名前をつける」ことです。
フォームはフォーム、一覧は一覧、1件表示は1件表示、と分けておくと、
後から修正するときに「どこを触ればいいか」がすぐ分かります。
挑戦課題 state設計も紙に書く
どのコンポーネントがどのstateを持つかを決める
次のステップは、「state をどこに置くか」を紙に書くことです。
学習ログアプリの例だと、必要な状態はだいたいこうなります。
学習ログの配列(全件)
フォームの入力値(日付・内容・時間)
読み込み中かどうか(API を使うなら)
エラーがあるかどうか
これを、さっきのコンポーネント構造に割り当てていきます。
LearningLogPage
├─ state: learningLogs(学習ログの配列)
├─ state: isLoading, error(必要なら)
├─ AppHeader
├─ LearningLogForm
│ └─ state: date, title, minutes(フォーム入力)
└─ LearningLogList
└─ LearningLogItem(stateなし、propsだけ)
ポイントはこうです。
学習ログの配列は、一覧もフォームも関係する「アプリ全体の状態」なので、LearningLogPage が持つ。
フォームの入力値は、フォームの中だけで完結しているので、LearningLogForm が持つ。LearningLogList と LearningLogItem は、「渡されたログを表示するだけ」のコンポーネントにして、state を持たない。
この「誰が何を知っているべきか」を紙に書いて整理するのが、state 設計の練習です。
矢印で「データの流れ」も書いてみる
もう一歩踏み込むなら、データの流れも矢印で書いてみてください。
フォームから親へ:LearningLogForm が「新しいログを追加して」と親に依頼する(onAdd props)。
親から一覧へ:LearningLogPage が learningLogs を LearningLogList に渡す。
一覧から親へ(削除など):LearningLogItem が「このログを削除して」と親に依頼する(onDelete props)。
テキストで表すと、こんな感じです。
LearningLogPage
├─ state: learningLogs
├─ handleAddLog(log) ← LearningLogForm から呼ばれる
├─ handleDeleteLog(id) ← LearningLogItem から呼ばれる
├─ LearningLogForm
│ └─ props: onAdd(= handleAddLog)
└─ LearningLogList
└─ props: logs(= learningLogs), onDelete(= handleDeleteLog)
ここまで紙に書けていれば、エディタを開いたときに
「何となく書き始める」のではなく、「設計図どおりに組み立てる」感覚でコードを書けます。
まとめ:設計練習で身につけてほしいこと
この課題で大事なのは、「コードを書く前に考える」習慣です。
画面を箱とラベルで描いて、「どこに何があるか」を目で見えるようにする。
箱をそのままコンポーネント名にして、「役割ごとに分ける」イメージを持つ。
state は「誰がその情報を知るべきか」で持ち場所を決め、親子関係とデータの流れを矢印で書いてみる。
ここまで紙に落とせるようになると、
実際にコードを書くときの迷いがかなり減ります。
