こんにちは、かつコーチです。
前回まででテスト・デプロイ・ビルド最適化と、開発から公開までの一連の流れを見てきました。
ここからは実践Tips編として、Reactを書いていると誰もが一度はぶつかる定番エラーを、原因と解決法つきでまとめて紹介します。
「エラーメッセージで検索してこの記事にたどり着いた」という人にも使えるように、症状別に整理しました。
エラーとの向き合い方
エラーメッセージは「敵」ではなく「ヒント」
Reactを学び始めたばかりの頃は、赤いエラー画面が出るだけで焦ってしまいがちです。
ですが、Reactのエラーメッセージは原因の場所と理由をかなり具体的に教えてくれることが多く、慣れると強力な手がかりになります。
エラーが出たら、まずメッセージの中で「どのファイルの、何行目で、何が原因か」を書いている部分を探す癖をつけましょう。
スタックトレースの読み方
エラーメッセージの下に続く英数字の羅列はスタックトレース(エラーが発生するまでの処理の呼び出し順)と呼ばれ、上から順に「どの関数がどの関数を呼び出してエラーに至ったか」が記録されています。
一番上に書かれている自分のコードのファイル名・行数に注目すると、原因箇所を素早く特定できます。
よくあるエラー1:「Cannot read properties of undefined」
発生する原因
データがまだ取得できていない段階で、そのデータのプロパティにアクセスしようとすると発生するエラーです。
Cannot read properties of undefined (reading 'name')
API通信の結果を待たずにレンダリングしてしまう、Reactの初心者が最も多く遭遇するエラーの1つです。
❌ Before:データ取得前にプロパティへアクセスしてしまう
import { useEffect, useState } from "react";
function UserProfile() {
const [user, setUser] = useState<{ name: string } | undefined>();
useEffect(() => {
fetch("/api/user")
.then((res) => res.json())
.then((data) => setUser(data));
}, []);
// 初回レンダリング時、userはまだundefinedのまま
return <p>ようこそ、{user.name}さん</p>;
}
useStateの初期値がundefinedのまま最初のレンダリングが走るため、user.nameにアクセスした瞬間にエラーになります。
✅ After:データが存在するかを先に確認する
import { useEffect, useState } from "react";
function UserProfile() {
const [user, setUser] = useState<{ name: string } | undefined>();
useEffect(() => {
fetch("/api/user")
.then((res) => res.json())
.then((data) => setUser(data));
}, []);
if (!user) {
return <p>読み込み中...</p>;
}
return <p>ようこそ、{user.name}さん</p>;
}
if (!user)で「まだデータがない状態」を先に処理してから本来の表示に入ることで、存在しないプロパティへのアクセスを防げます。
私が初心者だった頃は、このエラーが出るたびに「なぜ動かないんだ」と混乱していましたが、「レンダリングは何度も呼ばれる。最初の1回は空データで呼ばれるかもしれない」という前提で書く、と意識してから激減しました。
よくあるエラー2:「Objects are not valid as a React child」
発生する原因
配列やオブジェクトを、そのまま{ }の中に書いて表示しようとすると発生します。
Objects are not valid as a React child (found: object with keys {id, name})
❌ Before:オブジェクトをそのまま表示しようとする
function UserCard({ user }: { user: { id: number; name: string } }) {
// userオブジェクトそのものを表示しようとしている
return <div>{user}</div>;
}
Reactは文字列・数値・配列(の中身が表示可能な要素)は表示できますが、オブジェクトをそのまま画面に描画する方法を知らないため、このエラーになります。
✅ After:表示したいプロパティを指定する
function UserCard({ user }: { user: { id: number; name: string } }) {
return <div>{user.name}</div>;
}
console.log(user)で中身を確認すると、意外と見落としがちな「配列の中に入れ忘れていた」「余計な階層があった」というミスに気づけることが多いです。
よくあるエラー3:「Too many re-renders」
発生する原因
レンダリング中にsetState(状態更新関数)を無条件に呼び出してしまい、更新→再レンダリング→更新→…という無限ループに陥っている状態です。
❌ Before:レンダリング中に直接setStateを呼び出す
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
// ボタンのonClickではなく、レンダリング処理の中で直接呼んでしまっている
setCount(count + 1);
return <p>カウント: {count}</p>;
}
setCountをレンダリング処理の直下で呼ぶと、状態が更新されるたびに再レンダリングが走り、そのたびにまたsetCountが呼ばれる、という無限ループになります。
✅ After:イベントハンドラの中で呼び出す
import { useState } from "react";
function Counter() {
const [count, setCount] = useState(0);
const handleClick = () => {
setCount(count + 1);
};
return (
<div>
<p>カウント: {count}</p>
<button onClick={handleClick}>+1</button>
</div>
);
}
setStateは、コンポーネント本体の直下ではなく、イベントハンドラやuseEffectの中で呼ぶ、というルールを徹底すれば防げるエラーです。
よくあるエラー4:「Each child in a list should have a unique key prop」
発生する原因
mapで要素の一覧を描画する際に、key属性を指定していない、あるいは指定方法が不適切な場合に表示される警告です。
Warning: Each child in a list should have a unique "key" prop.
このエラーは動作自体が止まるものではなく警告ですが、放置するとリストの表示がおかしくなるバグの温床になります。
function TodoList({ todos }: { todos: { id: number; title: string }[] }) {
return (
<ul>
{todos.map((todo) => (
<li key={todo.id}>{todo.title}</li>
))}
</ul>
);
}
配列のインデックスではなく、データが持つ一意なID(todo.idなど)をkeyに指定するのが基本です。
このエラーの詳しい仕組みと対処法は、次回の記事でさらに詳しく掘り下げます。
エラー解決の共通ステップ
かつコーチが実践している調査の順番
私がエラーに遭遇したとき、毎回この順番で調べるようにしています。
- エラーメッセージ全文をそのままコピーし、どのファイル・何行目かを確認する
- その行の周辺で、
undefinedになっている可能性のある値がないかconsole.logで確認する - メッセージの内容(英語)を素直に読み、「〇〇できない」の〇〇が何を指しているかを特定する
- 同じメッセージで検索し、他の人がどう解決したかを参考にする
この順番を守るようになってから、エラー対応にかかる時間が体感で半分近くになりました。
焦って闇雲にコードを書き換える前に、まずメッセージを最後まで読む、これがエラー対応の一番の近道です。
まとめ
この記事のポイント
- エラーメッセージは原因特定のヒントであり、まず全文を読むことが大切
- 「Cannot read properties of undefined」はデータ未取得時のアクセスが主な原因
- 「Objects are not valid as a React child」はオブジェクトをそのまま表示しようとした際に発生する
- 「Too many re-renders」はレンダリング中の直接的なsetState呼び出しが原因
- エラー対応は「メッセージを読む→該当箇所を特定→console.logで確認→検索」の順番が近道
次に読むべき記事
エラー解決編の次は、key属性まわりでよく出る「keyがありません」警告の意味と対処法を、もう少し掘り下げて解説します。
→ 次の記事:「keyがありません」警告の意味と対処法
