Rork アプリが React Native / Expo ベースである理由
Rork が生成するモバイルアプリは、内部的に React Native + Expo で構築されています。このため、React Native 固有のランタイムエラーが発生することがあります。これらのエラーは一度理解すれば、以降のアプリ開発で繰り返し遭遇する同じパターンなので、今のうちに解決方法を習得しておく点が肝心です。
よくあるランタイムエラー TOP 5
1. TypeError: undefined is not an object
症状: アプリが起動直後にクラッシュし、コンソールに TypeError: undefined is not an object と表示されます。
原因: State(状態)の初期化を忘れているケースが大半です。
// ❌ 間違い: state の初期値がない
import { useState } from "react";
import { View, Text, FlatList } from "react-native";
export default function ProductList() {
const [products, setProducts] = useState(); // undefined として初期化される
return (
<FlatList
data={products} // undefined.map() を呼ぼうとしてエラーになる
renderItem={({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item) => item.id}
/>
);
}
// ✅ 正しい: 空配列で初期化
export default function ProductList() {
const [products, setProducts] = useState([]); // 空配列で初期化
return (
<FlatList
data={products} // 安全に反復できる
renderItem={({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item) => item.id}
/>
);
}解決方法:
useState(undefined)ではなく、適切な初期値(空配列[]、デフォルトオブジェクト{}、など)を指定する- データ取得完了まで UI を条件付きレンダリングする(
if (!data) return <Loading />)
2. Invariant Violation: Text strings must be rendered within a component
症状: コンソールに Invariant Violation: Text strings must be rendered within a <Text> component と表示され、赤い画面が出現します。
原因: React Native では、**テキスト文字列を直接 <View> に入れることができません。**すべてのテキストは <Text> コンポーネントでラップする必要があります。
// ❌ 間違い: テキストが <Text> にラップされていない
import { View } from "react-native";
export default function App() {
return (
<View>
Hello World {/* エラー! */}
</View>
);
}
// ✅ 正しい: <Text> コンポーネントを使う
import { View, Text } from "react-native";
export default function App() {
return (
<View>
<Text>Hello World</Text> {/* OK */}
</View>
);
}解決方法:
- すべてのテキスト文字列を
<Text>でラップする - Rork の AI がこのパターンを検出できるよう、生成時に「React Native では Text コンポーネントを必ず使う」と指示する
3. Error: Rendered more hooks than during the previous render
症状: 画面を操作した後、コンソールに Error: Rendered more hooks than during the previous render が表示されます。
原因: React Hooks のルール違反です。以下の 2 つのパターンが典型的です:
- Hooks を条件分岐内で呼ぶ —
if (condition) { useState(...) }はダメ - ループ内で Hooks を呼ぶ —
items.map(() => useEffect(...))はダメ
// ❌ 間違い: 条件分岐内で useState を呼ぶ
import { useState } from "react";
import { View, Button, Text } from "react-native";
export default function Counter() {
const [isEnabled, setIsEnabled] = useState(false);
// ❌ このif文の中でuseStateを呼ぶと、条件によってHooks数が変わる
if (isEnabled) {
const [count, setCount] = useState(0);
}
return (
<View>
<Button title="Enable" onPress={() => setIsEnabled(!isEnabled)} />
</View>
);
}
// ✅ 正しい: すべての Hooks を関数のトップレベルで呼ぶ
export default function Counter() {
const [isEnabled, setIsEnabled] = useState(false);
const [count, setCount] = useState(0); // トップレベルで呼ぶ
return (
<View>
<Button title="Enable" onPress={() => setIsEnabled(!isEnabled)} />
{isEnabled && <Text>Count: {count}</Text>}
</View>
);
}解決方法:
- Hooks ルール: Hooks は常にコンポーネントのトップレベルで呼ぶ(条件分岐やループの中では呼ばない)
useState/useEffect/useCallbackなど、すべての React Hooks が対象
4. Module not found / Cannot resolve module
症状: ビルド時またはアプリ起動時に Module not found: Can't resolve 'react-native-gesture-handler' のようなエラーが出る。
原因: インストールされていないパッケージを import したか、バージョンの不整合があります。
// ❌ インストールされていないパッケージをimport
import { GestureHandlerRootView } from "react-native-gesture-handler"; // インストールされていない
// ✅ 解決: npm install で追加
// $ npm install react-native-gesture-handler expo-gesture-handler解決方法:
npm install {パッケージ名}でパッケージをインストール- 既にインストール済みなら
npm installを実行して依存関係を再インストール - React Native / Expo のバージョンと互換性を確認(Expo の公式マトリックスを参照)
- キャッシュをクリア:
npx expo start --clear
5. White Screen of Death(白画面)— エラーバウンダリの活用
症状: アプリが起動しても何も表示されず、真っ白な画面が続く。コンソールにはエラーが出ていません。
原因: JavaScript エラーが発生しているが、エラー処理がされておらず、ユーザーに何も表示されていません。
解決方法: エラーバウンダリ(Error Boundary) コンポーネントを実装します。
// components/ErrorBoundary.tsx
import { View, Text, ScrollView } from "react-native";
import { ReactNode } from "react";
interface Props {
children: ReactNode;
}
interface State {
hasError: boolean;
error: Error | null;
}
// エラーバウンダリ: 子コンポーネントで発生したエラーをキャッチして表示
export class ErrorBoundary extends React.Component<Props, State> {
constructor(props: Props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
componentDidCatch(error: Error, errorInfo: any) {
console.error("ErrorBoundary caught:", error, errorInfo);
}
render() {
if (this.state.hasError) {
return (
<ScrollView contentContainerStyle={{ padding: 20, justifyContent: "center" }}>
<Text style={{ fontSize: 18, fontWeight: "bold", color: "red", marginBottom: 10 }}>
⚠️ エラーが発生しました
</Text>
<Text style={{ fontSize: 14, color: "#666", marginBottom: 10 }}>
{this.state.error?.message || "不明なエラー"}
</Text>
<Text style={{ fontSize: 12, color: "#999", fontFamily: "monospace" }}>
{this.state.error?.stack}
</Text>
</ScrollView>
);
}
return this.props.children;
}
}使い方:
// App.tsx
import { ErrorBoundary } from "./components/ErrorBoundary";
export default function App() {
return (
<ErrorBoundary>
<YourMainApp />
</ErrorBoundary>
);
}これでアプリが落ちるかわりに、エラー内容がユーザーに表示されます。
Rork のエラーログの読み方
Rork が生成するアプリでエラーが発生した場合、どこを見ればいいか を知ることが解決への第一歩です。
コンソールメッセージの階層
- 青色メッセージ — デバッグ情報(無視してOK)
- 黄色メッセージ — 警告(改善推奨)
- 赤色メッセージ — エラー(修正必須)
エラーメッセージの読み方のコツ
Error: Invariant Violation: Text strings must be rendered within a <Text> component
at node_modules/react-native/Libraries/Text/Text.js:100
in MyComponent (at screens/HomeScreen.tsx:25)
この場合:
- 何が起きた? → Text strings must be rendered within a Text component
- どこで? → MyComponent
- そのコンポーネントはどこ? → screens/HomeScreen.tsx の 25 行目
このように、エラーメッセージの上から順に読むことで、問題の箇所を特定できます。
Fix Now(自動デバッグ)機能の活用法
Rork では、エラー検出時に Fix Now 機能を使うことで、AI が自動的にコードを修正してくれます。
- エラーが表示されたら、スクリーンショットを撮ってコピー
- Rork チャットに貼り付けて「Fix Now」をクリック
- AI が修正コードを生成し、アプリに自動適用される
Fix Now が成功したら、修正内容を確認して理解することが大事。その修正パターンを次に生かせます。
Expo Go vs Development Build での違い
Expo Go(プレビューアプリ)と Development Build(カスタムビルド)では、発生するエラーが異なることがあります。
| 状況 | Expo Go | Development Build |
|---|---|---|
| ネイティブモジュール(カメラなど)未対応 | 実行できない | 実行できる |
| パフォーマンス | 遅い(デバッグ情報込み) | 速い |
| デバッグ情報 | 詳細 | 少ない |
| 本番環境に近い | いいえ | はい |
Expo Go でエラーが出ない = 本番環境でも安全 とは限りません。Development Build でテストしましょう。
Rork Companion アプリでの実機デバッグ
Rork Companion(Mac アプリ)を使うと、実機でのデバッグが格段に楽になります。
- ライブログ表示 — デバイスのコンソール出力をリアルタイムで表示
- ホットリロード — コード変更時に自動反映
- デバイス選択 — 複数デバイスでの同時テスト
Rork Companion の詳しい使い方は「Rork Companion Mac App」を参照してください。
全体を振り返って
Rork で発生する React Native / Expo ランタイムエラーは、一度理由を理解すれば繰り返し学習できます。
- State の初期化 — 必ず適切な初期値を指定する
- Text コンポーネント — すべてのテキストをラップする
- Hooks ルール — 条件分岐やループの外で呼ぶ
- モジュール互換性 — バージョン確認と npm install を忘れずに
- エラーバウンダリ — 白画面を防ぐために必須
こうしたパターンをマスターすると、Rork でのアプリ開発がスムーズになります。
参考資料
開発中に参考になる書籍: