コース一覧
React道場 ハレノヒ珈琲をモダン化する10問
営業中バッジと時計

React道場 ハレノヒ珈琲をモダン化する10問

React の基本を終えた人が、白紙から部品を組み立てる演習専用コースです。解説はありません。依頼と完成条件だけを読み、自分で設計します。手が止まったときのために、方針・使う構文・部分解の3段階のヒントを各問に用意しています。props を受ける部品から始まり、state、条件付きのクラス、map での描画、絞り込み、制御コンポーネント、入力の検証を経て、最後は部品の分割と注文ウィジェットの完成まで、10問で React の主要な考え方を一巡します。1問15分から45分、全10問で約5時間です。React入門を終えて「写経はできるが白紙からは書けない」と感じている方に向いています。

1
初段
01. MenuCard部品を作れ15分
02. いいねボタン15分
03. ダークモード切替(React版)20分
04. メニュー一覧をmapで描画せよ20分
2
中段
01. カテゴリタブで絞り込め25分
02. 予約フォームを制御せよ25分
03. 入力エラーを表示せよ30分
04. 営業中バッジと時計30分
3
師範
01. 肥大部品を分割せよ35分
02. 総合 注文ウィジェット完成45分

営業中バッジと時計

中段 / 目安 30分

陽葵さんがJS道場のときの画面を思い出しながら聞いてきます。「営業中バッジと時計、モダン化後も欲しい! Reactだとタイマーってどう扱うの?」。

ここで初めて useEffect を触ります。これまで書いてきたのは「state を受け取って画面を返す」だけの、外の世界と関わらない部品でした。ところがタイマーを動かす、通信する、といった処理は画面を返すのとは別の仕事です。こういう描画の外側で起こす処理を副作用と呼び、React では useEffect の中に置きます。

JavaScript (JSX)

useEffect(() => { const id = setInterval(() => { setTick((t) => t + 1); }, 1000); return () => clearInterval(id); }, []);

3つの部分に分かれています。中身が始めたい処理、return で返す関数が片付け、末尾の [] がいつ動かすかの指定です。

[] は「最初の1回だけ」を意味します。ここを書き忘れると、部品が描き直されるたびに新しいタイマーが増え、1秒に何十回も動く画面ができあがります。

そして return の片付けです。これを書かないと、部品が画面から消えたあともタイマーは回り続け、もう無い部品の state を触ろうとします。始めたものは自分で終わらせる、それが useEffect の作法です。書いておくと React が消えるときに呼んでくれます。

さて、時計そのものの判定について正直に言っておきます。「今の時刻を出す」コードは、実行するたびに答えが変わるので採点できません。だから今回は、JS道場の問8・問9と同じ手を使います。時刻を引数で受け取る形に切り出し、テスト用のボタンでいくつかの時刻を試すのです。

具体的には、時・分・秒を受け取って 09:05:03 の形に整える関数と、時を受け取って営業中かを返す関数の2つを作ってもらいます。これらは引数だけで答えが決まるので、何度動かしても同じ結果になり、確かめようがあります。時刻に依存する処理を、依存しない小さな関数として切り出すのは実務でもそのまま使う考え方です。

そのうえで useEffect と clearInterval は完成条件に残します。判定はできませんが、書く練習をしないと身につきません。片付けを書かなかった人がどうなるかは、師範いわくデバッグ道場の問6で分かるそうです。

完成条件

  • 時・分・秒を受け取り 09:05:03 のようにゼロ埋めして返す関数を作り、className が clock の要素に出す
  • 時を受け取り、7以上22未満なら営業中と判定する関数を作る
  • className が badge の要素に、営業中なら「営業中」と open クラス、そうでなければ「準備中」と closed クラスを付ける
  • 時刻ボタンを押すと、時計と バッジの両方がその時刻のものに変わる
  • useEffect の中で setInterval を始め、return で clearInterval して片付ける。依存配列は空にする

進め方

先に整形と営業判定の2つの関数を作り、ボタンで切り替わるところまで仕上げてください。そこが通れば問題の主要部は終わりです。useEffect は最後に足します。

ゼロ埋めは String(n).padStart(2, "0") が手軽です。

badge のクラスは className={"badge " + (open ? "open" : "closed")} のように組み立てます。badge を消してしまうと見た目が丸ごと崩れるので、必ず残したまま足してください。

ヒントは3段階で、①方針、②使う構文、③部分解の順に出ます。1つも開けずに通せたら、その問題は自分のものです。

ヒント

前のヒントを開くと次が開きます。開かずに解けると未開封クリアです

①方針 「今の時刻」を直接あちこちで読むのではなく、時刻を引数で受け取って答えを返す小さな関数を2つ作ります。整形するものと、営業中かを判定するもの。画面はその戻り値を出すだけにしてください。

ヒント 2ヒント 1 を開くと読めます
ヒント 3ヒント 2 を開くと読めます
App.jsx
styles.css
プレビュー

できているか

  • 9時5分3秒を選ぶと 09:05:03 と出て営業中になる
  • 23時を選ぶと 23:00:00 と出て準備中に切り替わる
  • 6時30分はまだ準備中で、18時42分7秒は営業中である
  • 18時42分7秒に戻すと 18:42:07 と出て営業中に戻る
エディタを読み込んでいます