コース一覧
フロントデバッグ道場 呪われたウィジェット供養の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分

一つ前の値が表示される

中段 / 目安 30分

琥珀さんが検索欄に文字を打ちながら、首をかしげています。「検索欄、『こ』って打つと空欄の結果、『こは』って打つと『こ』の結果……常に一文字ぶん過去を生きてるんだ」。

打った文字そのものは className が echo の段落に正しく出ています。ずれているのは結果の一覧だけです。1回打つごとに、1つ前の検索語で絞り込んだ結果が出てきます。

呪いの正体は set 関数は予約であって、即時の代入ではない という React の性質です。

JavaScript (JSX)

setWord(e.target.value); console.log(word); // まだ古い値

setWord を呼んだ瞬間に word という変数が書きかわるわけではありません。React に「次の描画ではこの値にしてください」と伝えているだけです。いま動いている関数の中の word は、この描画が始まったときの値のまま、最後まで変わりません。

これは不便な仕様に見えますが、そうではありません。1回の描画の間、同じ名前が途中で別の値に化けないからこそ、コードは上から下へ素直に読めます。React はこの性質を保つために、set をあえて予約にしています。

では、更新後の値はどこで手に入るのか。答えは2つあります。

1つめは 次の描画を待つ ことです。set した値が反映された word は、次にコンポーネント関数が呼び直されたときに手に入ります。効果や描画の中で使うぶんにはこれで足ります。

2つめ、そして今回いちばん素直なのは、イベントが持ってきた値をそのまま使う ことです。入力欄が変わったときに渡ってくる e.target.value は、いま打たれたばかりの新しい文字です。state を経由せず、その値で絞り込んでしまえば、一文字ぶんの遅れは起きません。

JavaScript (JSX)

const next = e.target.value; setWord(next); // この next を使って絞り込む

state をいったん名前の付いた変数に受けておくのが、この手の呪いを二度と呼ばないコツです。set に渡すのも絞り込みに使うのも同じ next になるので、片方だけ古いという状態が作れなくなります。

完成条件

  • 入力欄に打った文字と、className が hit の要素に出る結果が常に一致する
  • 「こ」と打った直後に、こはく堂とこまち食堂の2件が出ている
  • 続けて「みど」と打つと、結果の先頭がみどり書房に入れ替わる
  • 検索語の表示 (className が echo の段落) は今までどおり打った文字を出す

進め方

まず症状を正確に言葉にしてください。「結果が出ない」ではなく「1つ前の検索語の結果が出る」です。ここまで言えていれば、犯人は「古い値を読んでいる場所」だと絞れます。

絞り込みの行に console.log(word, e.target.value) を入れて、2つを並べて見るのが一番早い切り分けです。片方だけ遅れているのが目で見えます。

直すのは1つの関数の中だけです。state の持ち方も画面の作りも変える必要はありません。

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

供養が済むと、カメ師範が奥から言います。「stateは未来への手紙だ。書いた直後に読み返しても、まだ届いていない」。

ヒント

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

①方針 結果が1つ前になるということは、絞り込みに使っている値が1つ古いということです。set 関数は予約であって即時の代入ではないので、呼んだ直後の state はまだ前の値のままです。いま打たれた文字をどこから手に入れるかを考えてください。

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

できているか

  • 「こ」と打つと、こ で始まる2件がその場で出る
  • 続けて「みど」と打つと、先頭がみどり書房に入れ替わる
  • 当たらない文字を打つと、見つかりませんに変わる
エディタを読み込んでいます