この課題のねらい
ここは「React を書ける人」から「バグを直せる人」に変わる仕上げのステップです。
どんなに上手いエンジニアでも、バグゼロで書くことはほぼありません。
大事なのは「バグを出さないこと」ではなく、「バグが出たときに落ち着いて原因を特定して直せること」です。
この課題では、
- 自分でエラーを“わざと”起こしてみる
- エラーメッセージをちゃんと読む
- console.log に頼りすぎずに、どこが怪しいかを絞り込む
このあたりの感覚を育てていきます。
必須課題:エラーを1つ再現して直す
わざとよくあるエラーを作ってみる
まずは「よくある初歩的なエラー」を、あえて自分で作ってみます。
例として、「存在しない変数を使ってしまう」パターンをやってみましょう。
"use client";
export default function DebugExample() {
const message = "こんにちは";
return (
<main style={{ padding: "24px", fontFamily: "sans-serif" }}>
<h1>デバッグ練習</h1>
<p>{mesage}</p>
</main>
);
}
TSXここ、わざと message ではなく mesage とタイプミスしています。
この状態でブラウザを開くと、画面にエラーが出ます。
エラーメッセージを「ちゃんと読む」練習
React や Next.js の開発環境では、エラーが出ると画面に赤いエラー画面が出ます。
そこにはだいたい次のような情報が載っています。
- 何行目でエラーが起きたか
- どんな種類のエラーか(ReferenceError, TypeError など)
- どの変数や関数が問題になっているか
今回の例だと、こんなメッセージが出るはずです(英語ですが、雰囲気でOK)。
ReferenceError: mesage is not defined
at DebugExample (…/page.tsx:行番号)
ここから読み取れることは、
- 「mesage という名前のものは定義されていない」
- つまり「自分で宣言していない変数を使っている」
ということです。
コードを見返すと、
const message = "こんにちは";
...
<p>{mesage}</p>
TSXとなっていて、message と mesage が微妙に違うのが分かります。
これを message に直せば、エラーは消えます。
「エラーを怖がらない」感覚を持つ
ここで一番大事なのは、
エラー画面は「怒られている」のではなく、「ヒントをくれている」
という感覚です。
- どのファイルの
- どの行で
- どんな種類の問題が起きているか
を、かなり親切に教えてくれています。
最初は英語にビビるかもしれないけれど、「単語を拾うだけ」でも十分役に立ちます。
もう一つの例:props の渡し忘れエラー
よくある「undefined に対して何かしようとしている」パターン
もう一つ、実務でもよくあるエラーを見てみましょう。
「props を渡し忘れて、undefined に対して何かしようとしてしまう」パターンです。
type GreetingProps = {
name: string;
};
function Greeting({ name }: GreetingProps) {
return <p>こんにちは、{name}さん</p>;
}
export default function DebugExample() {
return (
<main style={{ padding: "24px", fontFamily: "sans-serif" }}>
<h1>デバッグ練習 2</h1>
<Greeting />
</main>
);
}
TSXGreeting コンポーネントは name を必須 props として受け取るのに、
呼び出し側で <Greeting /> とだけ書いていて、name を渡していません。
この場合、TypeScript をちゃんと使っていればコンパイル時に怒られますが、
型チェックが甘いと、実行時にエラーになることもあります。
エラーメッセージとしては、
TypeError: Cannot read properties of undefined (reading ‘name’)
のようなものが出ることが多いです。
ここから読み取れるのは、
- 「undefined の何かから name を読もうとしている」
- つまり「name が存在しない状態で使われている」
ということです。
修正はシンプルで、
<Greeting name="太郎" />
TSXのように、ちゃんと name を渡してあげれば OK です。
挑戦課題:console.logなしで原因特定
「どこが怪しいか」を目で追う
console.log は強力な武器ですが、
「とりあえずあちこちに console.log を仕込む」だけだと、
いつまでもデバッグが上達しません。
挑戦課題では、あえて console.log を封印して、
- エラーメッセージ
- コードの流れ
- どの値が undefined になり得るか
を頭の中と目で追っていく練習をします。
さっきの props の例で考えてみましょう。
type GreetingProps = {
name: string;
};
function Greeting({ name }: GreetingProps) {
return <p>こんにちは、{name}さん</p>;
}
export default function DebugExample() {
return (
<main>
<Greeting />
</main>
);
}
TSXエラーは「name が undefined っぽい」と言っている。Greeting の中では { name } を受け取っている。Greeting を呼び出している場所を見ると、<Greeting /> だけで name を渡していない。
この流れを、console.log なしで追えるようになると、
「エラーが出たときに、どこからどこまでを疑えばいいか」が見えてきます。
型エラーやエディタの警告も「デバッガー」だと思う
もう一つ大事なのは、TypeScript やエディタの警告も「デバッグの味方」だということです。
- 赤い波線
- 型エラー
- 「この props は必須です」といった警告
これらは、実行前に「ここ怪しいよ」と教えてくれているサインです。
たとえば、さっきの Greeting の例なら、
VS Code などでは <Greeting /> のところに「name が足りない」と警告が出ます。
console.log に頼る前に、
- エディタの赤線がどこについているか
- TypeScript のエラーが何を言っているか
を一度ちゃんと読む習慣をつけると、
「そもそも実行前に防げるバグ」がかなり減ります。
デバッグの思考の順番
1. エラーを再現できる状態を作る
まず、「たまにしか起きない」「よく分からないけどたまに落ちる」状態だと、
原因特定がとても難しくなります。
- どの画面で
- どの操作をしたときに
- 毎回同じようにエラーが出るか
をまず固める。
今回の課題では、「自分でエラーを作る」ので、ここはクリアしやすいです。
2. エラーメッセージを読む
次に、画面やコンソールに出ているメッセージをちゃんと読む。
全部理解しようとしなくてよくて、
- エラーの種類(ReferenceError, TypeError など)
- どの変数・プロパティが問題になっているか
- どのファイルの何行目か
このあたりだけでも拾えれば十分です。
3. 「その値が undefined になり得る場所」を探す
React のバグで多いのは、
- undefined や null に対して何かしようとしている
- props を渡し忘れている
- state の初期値が想定と違う
といったパターンです。
エラーに出ている変数やプロパティが、
- どこで定義されているか
- どこから渡されているか
をたどっていくと、「あ、ここで渡してない」「ここで typo してる」が見えてきます。
まとめ:デバッグでつかんでほしいこと
この仕上げ課題で、本当に持ち帰ってほしいのは次の感覚です。
- エラーは「怖いもの」ではなく、「ヒントの塊」。
- まずはエラーメッセージと行番号を見て、「どの変数・どの props が怪しいか」を絞り込む。
- console.log は最後の手段にして、その前に「コードの流れ」と「型・props の関係」を目で追ってみる。
ここが身についてくると、
- バグが出ても焦らない
- 「あーこれはだいたいこの辺だな」と当たりがつく
- 修正にかかる時間がどんどん短くなる
という、エンジニアとしての“地力”がぐっと上がります。
