MeWrite Docs

React: Cannot read properties of undefined

ReactでuseState/useEffectを使った非同期データ処理時に発生するTypeError

概要

ReactでTypeError: Cannot read properties of undefinedが発生する主な原因は、非同期でデータを取得する前にレンダリングが実行されることです。useStateの初期値がnullundefinedのまま、その値のプロパティにアクセスしようとしてエラーになります。

エラーメッセージ

TypeError: Cannot read properties of undefined (reading 'name')
TypeError: Cannot read properties of null (reading 'map')

発生パターン

パターン1: 初回レンダリング時にデータがない

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
function UserProfile() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchUser().then(data => setUser(data));
  }, []);

  // NG: 初回レンダリング時、userはnullなのでエラー
  return <h1>{user.name}</h1>;
}

パターン2: 配列データのmap前にnullチェックなし

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function UserList() {
  const [users, setUsers] = useState(null);

  useEffect(() => {
    fetchUsers().then(data => setUsers(data));
  }, []);

  // NG: usersがnullの状態でmapを呼ぶとエラー
  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

パターン3: propsがundefined

1
2
3
4
5
6
7
8
9
function UserCard({ user }) {
  // NG: 親がuserを渡し忘れるとエラー
  return <h1>{user.name}</h1>;
}

// 親コンポーネント
function App() {
  return <UserCard />; // userを渡していない
}

解決策

1. 条件付きレンダリング(早期リターン)

最も明確な方法。ローディング状態も表示できます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
function UserProfile() {
  const [user, setUser] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    fetchUser()
      .then(data => setUser(data))
      .finally(() => setLoading(false));
  }, []);

  // 早期リターンでガード
  if (loading) return <p>Loading...</p>;
  if (!user) return <p>User not found</p>;

  return <h1>{user.name}</h1>;
}

2. オプショナルチェイニング

シンプルにundefinedを許容する場合。

1
2
3
4
5
6
7
8
9
function UserProfile() {
  const [user, setUser] = useState(null);

  useEffect(() => {
    fetchUser().then(data => setUser(data));
  }, []);

  return <h1>{user?.name ?? 'Loading...'}</h1>;
}

3. 配列の初期値を空配列にする

mapを使う場合は初期値を[]にするのがベスト。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function UserList() {
  // OK: 初期値を空配列にする
  const [users, setUsers] = useState([]);

  useEffect(() => {
    fetchUsers().then(data => setUsers(data));
  }, []);

  return (
    <ul>
      {users.map(user => <li key={user.id}>{user.name}</li>)}
    </ul>
  );
}

4. propsにデフォルト値を設定

1
2
3
4
5
6
7
8
9
// デフォルト引数
function UserCard({ user = {} }) {
  return <h1>{user.name ?? 'Unknown'}</h1>;
}

// または defaultProps(クラスコンポーネント向け)
UserCard.defaultProps = {
  user: {}
};

5. TypeScriptで型安全にする

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
interface User {
  id: number;
  name: string;
}

function UserProfile() {
  const [user, setUser] = useState<User | null>(null);

  useEffect(() => {
    fetchUser().then(data => setUser(data));
  }, []);

  // TypeScriptがnullチェックを強制
  if (!user) return <p>Loading...</p>;

  return <h1>{user.name}</h1>; // 型安全
}

カスタムフックで再利用

データ取得パターンを共通化すると安全です。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    fetch(url)
      .then(res => res.json())
      .then(setData)
      .catch(setError)
      .finally(() => setLoading(false));
  }, [url]);

  return { data, loading, error };
}

// 使用例
function UserProfile({ userId }) {
  const { data: user, loading, error } = useFetch(`/api/users/${userId}`);

  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  if (!user) return <p>Not found</p>;

  return <h1>{user.name}</h1>;
}

よくある間違い

  • useEffectの依存配列の設定ミス: 依存配列が空だと初回のみ実行、依存値があると再実行される
  • 非同期関数をuseEffect内で直接定義しない: クリーンアップ処理ができなくなる
  • stateの更新が非同期であることを忘れる: setState直後に新しい値を参照してもまだ古い値

関連エラー

関連エラー

JavaScript の他のエラー

最終更新: 2026-02-03