コース一覧
フロントデバッグ道場 呪われたウィジェット供養の10問
赤いエラーを読んで直せ

フロントデバッグ道場 呪われたウィジェット供養の10問

React で書かれた壊れたウィジェットを、自分の手で直していく演習専用コースです。解説はありません。症状と完成条件だけを読み、原因を突き止めて直します。手が止まったときのために、方針・調べ方・部分解の3段階のヒントを各問に用意しています。他の道場と違い、白紙からではなく「動いているように見えて壊れているコード」から始まります。関数名のタイポ、フォームの既定動作、key 忘れ、プロパティ名の取り違えといった見つけやすい呪いから始まり、state の直接変更、useEffect の無限ループ、set 直後の古い値、非同期応答の追い越しといった再現しにくい呪いへ進み、最後は5つの呪いが同時にかかったウィジェットを1つずつ払います。1問15分から45分、全10問で約4.5時間です。React入門を終えて「エラーが出ると手が止まる」と感じている方に向いています。

1
初段
01. ボタンが反応しない15分
02. 送信すると消える15分
03. 黄色い警告を消せ20分
04. undefined が出る20分
2
中段
01. 数字が増えない25分
02. 無限ループを止めろ25分
03. 一つ前の値が表示される30分
04. 検索結果が入れ替わる30分
3
師範
01. 赤いエラーを読んで直せ35分
02. 総合 5つの呪いを全部払え45分

赤いエラーを読んで直せ

師範 / 目安 35分

琥珀さんがスマホの画面をこちらに向けます。「営業さんから『画面が真っ赤』ってスクショだけ送られてきた。スタックトレースを読んで、犯人のファイルと行番号を特定してから直してほしいんだ」。

今回のウィジェットは、お店台帳です。開いた瞬間に落ちます。1件も出ません。エラーはこう出ています。

プレーンテキスト

TypeError: Cannot read properties of undefined (reading 'tel') at ShopCard (App.jsx:31:36) at ...

この道場でいちばん大事な回です。エラー文は犯行声明です。読めば、直す場所はほぼ書いてあります。

順番に読みます。まず1行目、TypeError は「値の型が想定と違う」種類のエラーです。続く Cannot read properties of undefined (reading 'tel') は日本語にするとこうなります。「undefined の中の tel を読もうとした」。つまり なにか.tel と書いた場所で、その なにか が undefined だった、ということです。

次に at ShopCard (App.jsx:31:36) を読みます。これは「App.jsx の31行目36文字目、ShopCard という関数の中で起きた」です。スタックトレースは上にあるものほど現場に近いので、一番上の、自分が書いたファイルを指している行が捜査の出発点です。ライブラリの中を指す行は通り道であって、犯人ではありません。

ここまでで、犯人は「ShopCard の中で .tel を読んでいる行」だと確定しました。そこには shop.contact.tel と書いてあります。.tel の手前は shop.contact なので、undefined だったのは shop.contact です。

最後に、なぜ undefined なのかを見ます。データを目で追うと、3件目のみどり書房に contact が付いていません。移転の届け出中でまだ連絡先が入っていない、実際にありがちな形です。データは直しません。 現実の API はこちらの都合で必ず埋まってはくれないので、欠けていても落ちない画面を作るのがフロント側の仕事です。

守り方は2つ組み合わせます。

1つめは optional chaining です。shop.contact?.tel と書くと、shop.contact が undefined や null のときは、そこで止まって undefined を返します。落ちません。

2つめは 無かったときに何を出すか決めること です。undefined を素通しすると画面に何も出ないか、場合によっては文字として undefined が出ます。問4で琥珀さんが「商店街の恥」と言っていたあれです。値が無いときは「準備中」のような、人が読んで意味の分かる文に置きかえてください。

JavaScript (JSX)

const tel = shop.contact?.tel; // tel が無ければ「準備中」を出す

hours はもう一段深く、shop.contact.hours.open です。contact が無い時点で hours も無いので、hours をいったん変数に受けて、有るときだけ時刻の文を組み立てるのが読みやすい形になります。

完成条件

  • 画面が落ちず、className が shop のカードが4枚並ぶ
  • 連絡先のあるお店は、今までどおり電話番号と営業時間が出る
  • 連絡先の無いみどり書房も落ちずに出て、電話と営業時間の欄には準備中であることが分かる文が出る
  • 画面のどこにも undefined という文字を出さない
  • データ (SHOPS) は書きかえない

完成の前に、原因を言葉にする

ファイルとして提出する報告書はありませんが、直す前に次の3つを自分の言葉で言えるようにしてください。デバッグで本当に身に付くのはここです。

  1. どこで落ちたか — ファイル名と行、そしてその中のどの式か
  2. なぜ落ちたか — どの値が undefined で、なぜ undefined だったのか
  3. どう直したか — 値が欠けていても落ちない形にした、そのやり方

言えないまま直すと、次に同じ形の呪いが出たときにまた最初から迷います。

進め方

エラーが出ている状態から始めてください。まずエラー文を最後まで読み、行番号のところをエディタで開きます。そこに書いてある式を、左から順に「これは undefined になり得るか」と問い直していくと、犯人の位置が1つに絞れます。

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

供養が済むと、カメ師範が短く言います。「エラー文は犯行声明だ。全文読む者だけが探偵になれる」。

ヒント

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

①方針 エラー文の `Cannot read properties of undefined (reading 'tel')` は「undefined の中の tel を読もうとした」という意味です。`.tel` の手前に書いてある式が undefined だった、ということなので、その式が undefined になり得るデータを台帳の中から探してください。データを埋めて直すのは供養ではありません。

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

できているか

  • お店のカードが4枚並んでいる
  • 連絡先のあるお店は電話番号が出ている
  • 連絡先の無いお店の電話欄に準備中の文が出ている
  • 連絡先の無いお店の営業時間欄に準備中の文が出ている
エディタを読み込んでいます