RORK LABEN
PLAY — Google Play の target API level 36 要件が昨日8月31日に発効しました。今日以降、新規アプリと既存アプリの更新は Android 16 対応が必須ですVISIBILITY — API 35 のままのアプリは掲載こそ続きますが、新しい Android 版のユーザーには表示されなくなります。エラーが出ないまま新規インストールだけが減る点に注意が要りますEXTENSION — 間に合わなかった場合は、Play Console から2026年11月1日までの延長申請が出せます。恒久対応の計画とセットで進めるのが実務的ですAPPLE — Apple 側は9月9日にイベント、iOS 27 の正式リリースは9月14日と報じられています。生成したアプリの iOS 27 実機確認はリリース週の前に済ませておきたいところですEXPO — Expo が expo-paste-input を公開しました(8月28日)。React Native の TextInput に画像・GIF・ステッカーの貼り付けを追加するネイティブモジュールですEAS — EAS Observe が8月20日に GA になりました。クラッシュや性能の観測を、ビルドや配信と同じ EAS 上で持てるようになっていますPLAY — Google Play の target API level 36 要件が昨日8月31日に発効しました。今日以降、新規アプリと既存アプリの更新は Android 16 対応が必須ですVISIBILITY — API 35 のままのアプリは掲載こそ続きますが、新しい Android 版のユーザーには表示されなくなります。エラーが出ないまま新規インストールだけが減る点に注意が要りますEXTENSION — 間に合わなかった場合は、Play Console から2026年11月1日までの延長申請が出せます。恒久対応の計画とセットで進めるのが実務的ですAPPLE — Apple 側は9月9日にイベント、iOS 27 の正式リリースは9月14日と報じられています。生成したアプリの iOS 27 実機確認はリリース週の前に済ませておきたいところですEXPO — Expo が expo-paste-input を公開しました(8月28日)。React Native の TextInput に画像・GIF・ステッカーの貼り付けを追加するネイティブモジュールですEAS — EAS Observe が8月20日に GA になりました。クラッシュや性能の観測を、ビルドや配信と同じ EAS 上で持てるようになっています
記事一覧/開発ツール
開発ツール/2026-04-30中級

Rork の『undefined is not an object』エラーを最短で特定する方法

Rorkで頻発する『undefined is not an object (evaluating ...)』エラーの読み解き方と、典型的な5つの原因をコード付きで解説します。Hermesのスタックが読みにくいときのデバッグ手順もまとめています。

Rork547Hermes8デバッグ22エラー対処3React Native234

Rork で生成されたコードを少し書き換えたら、いきなり赤い画面に「undefined is not an object (evaluating 'user.profile.name')」と表示された経験はありませんか。私も最初は「null チェックを足せば直るんでしょ」と高をくくっていたのですが、実際には参照しているプロパティそのものではなく、その上のオブジェクトが期待と違う形で返ってきている、というケースがほとんどでした。

このエラーは Hermes(Rork が標準で使う JavaScript エンジン)が「アクセスしようとした親が undefined だった」と教えてくれているメッセージです。原因は意外と少ないパターンに収束しますので、闇雲に ?. を足す前に、まず読み方とよくある落とし穴を押さえておくと、再発をぐっと減らせます。

まずエラーメッセージの『括弧の中』を必ず読む

このエラーで一番もったいないのが、undefined is not an object の文字だけ見て焦って手当てしてしまうことです。注目すべきはその後ろの (evaluating 'user.profile.name') の部分で、Hermes がどの式を評価したときに失敗したかをかなり正確に教えてくれます。

ERROR  undefined is not an object (evaluating 'user.profile.name')

この場合、問題は user.profile.name の評価ですが、Hermes の判定基準は「name を取り出そうとしたときに user.profile が undefined だった」です。つまり犯人は profile プロパティであって、user 自体や name ではない可能性が高い、ということになります。

デバッグの第一歩は『1つ手前で止めて中身を見る』こと

Rork で動かしているとスタックトレースが minify されたファイル名(例: index.bundle:135432)になりがちで、行番号からは原因が辿りにくいです。私は次のように一段ずつ console.log を仕込む方法を使っています。

// app/screens/Profile.tsx
function ProfileScreen({ route }) {
  const userId = route.params?.userId;
 
  // ❌ いきなり最深部にアクセスしてエラー
  // return <Text>{user.profile.name}</Text>;
 
  // ✅ 段階的に中身を確認
  const { data: user } = useUser(userId);
  console.log('[Profile] user:', user);
  console.log('[Profile] user.profile:', user?.profile);
 
  if (!user?.profile) {
    return <Text>プロフィールを読み込み中...</Text>;
  }
 
  return <Text>{user.profile.name}</Text>;
}

期待出力は [Profile] user: { id: 1, name: '...' } のように出るはずなのに、実際には [Profile] user.profile: undefined と出る、というように犯人がはっきり見えます。?. を足すこと自体は対症療法ですので、まず「なぜ profile が来ていないのか」を必ず確認してから防御コードを書くようにしています。

典型的な原因 5 つと、それぞれの直し方

1. API レスポンスのキー名が想定と違う

これが一番多いパターンだと感じています。バックエンド側で profileuserProfile にリネームしたのに、フロント側だけが古い名前のまま、という事故です。

// ❌ レスポンス構造が変わったのに気付いていない
const { data } = await fetch('/api/me').then(r => r.json());
return data.profile.name;  // → undefined is not an object
 
// ✅ レスポンスを一度確認するクセをつける
const json = await fetch('/api/me').then(r => r.json());
console.log('me response:', json);
const profile = json.user?.profile ?? json.profile ?? null;
if (!profile) throw new Error('profile が API から返ってきませんでした');
return profile.name;

2. useState の初期値が undefined のまま render される

// ❌ 初期値なしの useState に、初回render で深いアクセスする
const [user, setUser] = useState();  // 初期値が undefined
useEffect(() => {
  fetchUser().then(setUser);
}, []);
return <Text>{user.email}</Text>;  // ← 初回 render で爆発
 
// ✅ 初期値を設定し、未ロード時の表示を分ける
const [user, setUser] = useState(null);
useEffect(() => { fetchUser().then(setUser); }, []);
if (!user) return <ActivityIndicator />;
return <Text>{user.email}</Text>;

3. ネストした props の destructuring 忘れ

ナビゲーション周りでよく踏みます。useRouteuseLocalSearchParams の戻り値はキーが存在しないと undefined を返します。

// ❌ params が空のときに userId を取り出そうとして爆発
const { params: { userId } } = useRoute();
 
// ✅ 一段ずつ optional chaining で受ける
const route = useRoute();
const userId = route.params?.userId;
if (!userId) {
  // 開発中は throw すると気付きやすい
  if (__DEV__) console.warn('userId がありません', route);
  return null;
}

4. ネイティブモジュールの import を忘れている

@react-native-async-storage/async-storage のように、Expo prebuild が必要なライブラリで起こりがちです。Rork のプレビュー上は動いていても、実機ビルドだとモジュールが解決されず undefined のまま import される、という現象です。

import AsyncStorage from '@react-native-async-storage/async-storage';
 
// 実機で undefined になっていないかを開発時に確認
if (__DEV__ && !AsyncStorage) {
  console.error('AsyncStorage が読み込めていません。expo prebuild を確認してください');
}

EAS Build のログに Could not find module の警告が出ていないかも合わせて確認すると、原因の切り分けが早くなります。

5. useEffect で setState する前に値を参照している

非同期で取得した値を、まだ存在しない段階で読みに行ってしまうケースです。

// ❌ items がまだ未定義の段階で .map にかかる
useEffect(() => {
  fetch('/api/items').then(r => r.json()).then(setItems);
}, []);
return items.map(i => <Item key={i.id} item={i} />);
 
// ✅ 配列なら空配列で初期化しておくのが安全
const [items, setItems] = useState([]);  // ← undefined ではなく []
return items.map(i => <Item key={i.id} item={i} />);

配列の場合は useState([])、オブジェクトの場合は useState(null) にして「未ロード」と「中身が空」を区別できる状態を作るのが、私の中での定石です。

それでも特定できないときの最終手段

これらをチェックしても直らない場合、Hermes のスタックトレースの読み方を一段深めるのが有効です。Rork から Companion アプリに繋ぐと開発ビルドで sourcemap が有効になり、minify 前のファイル名と行番号が出るようになります。さらに、エラーが画面のどこで起きているかを切り分けるために、コンポーネントツリーを ErrorBoundary で部分的に囲み、原因の枝を機械的に絞り込む方法もあります。

function SafeBox({ name, children }) {
  return (
    <ErrorBoundary fallback={<Text>{name} で失敗しました</Text>}>
      {children}
    </ErrorBoundary>
  );
}
 
// ✅ 怪しい枝を1つずつ ErrorBoundary で包んで切り分ける
<SafeBox name="ProfileHeader">
  <ProfileHeader user={user} />
</SafeBox>
<SafeBox name="PostsList">
  <PostsList userId={user?.id} />
</SafeBox>

「画面全体が落ちる」を「特定のセクションだけが落ちる」に変えると、後の console.log もピンポイントで仕掛けられるようになります。

再発を減らすための日々の習慣

このエラーを根本的に減らすには、TypeScript で API レスポンスの型を厳密に書き、undefined の可能性を型レベルで強制するのが一番効きます。zod などのバリデーションを通せば、レスポンス形が変わったときにフロントの型と実体がずれることを防げます。型まわりのつまずきは TypeScript の型エラーが消えないときの直し方 にもまとめていますので、合わせて読んでみてください。React Native ランタイムで起きる他のエラーパターンも整理した React Native / Expo のランタイムエラー修正ガイド も参考になるはずです。

全体を振り返って

このエラーに出会ったら、まず (evaluating '...') の式をそのまま読み、一段手前のオブジェクトの実体を console.log で確認する、というクセを付けてみてください。?. を足して赤画面が消えても、データの形がそもそも想定と違っていれば、別の場所で必ず再発します。今日の自分のコードに useState() で初期値を省略している箇所がないかだけでも、ぜひ一度 grep してみると、思わぬ地雷が見つかるかもしれません。

シェア

お読みいただきありがとうございます

Rork Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥2,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

開発ツール2026-06-20
Rork が直せるバグと自分で直すバグを見分ける — エクスポートコードのトリアージ手順
Rorkに任せて直せるバグと、エクスポートしたReact Native/Expoコードを自分で手当てすべきバグを見分けるトリアージ手順です。エラーを層で分ける切り分け、非同期処理の握りつぶし、OSごとの挙動差、権限とATTの順序など5つの手当てを動くコードで示します。
開発ツール2026-06-17
Rork が自分で直せない3割を見極める — エクスポート前提の手直しワークフロー
Rork は遭遇したバグのおよそ7割を自力で直しますが、残り3割は手作業が必要です。再プロンプトで粘るべきか、エクスポートして自分で直すべきかを切り分ける判断基準と、動くコードでの手直し例をまとめました。
開発ツール2026-05-27
Rork × Hermes を本番で2ヶ月運用した所感 — 初回起動とメモリの実測値
Rorkで生成したアプリのHermesを有効にしたまま2ヶ月本番運用した実測記録です。初回起動が38%短縮された中身、Pixel 7でメモリ18%減、クラッシュフリー率の推移と注意点を、広告収益と直結する個人開発の運用感覚から振り返ります。計測環境も明記しています。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →