Why Rork Apps Use React Native and Expo
Rork-generated mobile apps are built on React Native + Expo under the hood. Because of this architecture, you'll occasionally encounter React Native-specific runtime errors. Once you understand these error patterns, you'll recognize and fix them quickly in all future projects. This guide walks you through the five most common runtime errors and how to solve them.
Top 5 Common Runtime Errors
1. TypeError: undefined is not an object
Symptom: The app crashes immediately after startup, and the console shows TypeError: undefined is not an object.
Root Cause: Forgetting to initialize state with an appropriate default value.
// ❌ Wrong: state initialized as undefined
import { useState } from "react";
import { View, Text, FlatList } from "react-native";
export default function ProductList() {
const [products, setProducts] = useState(); // Defaults to undefined
return (
<FlatList
data={products} // Trying to iterate over undefined → Error
renderItem={({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item) => item.id}
/>
);
}
// ✅ Correct: initialize with an empty array
export default function ProductList() {
const [products, setProducts] = useState([]); // Start with empty array
return (
<FlatList
data={products} // Safe to iterate
renderItem={({ item }) => <Text>{item.name}</Text>}
keyExtractor={(item) => item.id}
/>
);
}Solution:
- Always provide a sensible default value — empty array
[], empty object{}, ornull - Conditionally render UI while waiting for data:
if (!data) return <Loading />
2. Invariant Violation: Text strings must be rendered within a component
Symptom: The console shows Invariant Violation: Text strings must be rendered within a <Text> component and a red error screen appears.
Root Cause: React Native doesn't allow raw text inside <View>. All text must be wrapped in the <Text> component.
// ❌ Wrong: bare text in <View>
import { View } from "react-native";
export default function App() {
return (
<View>
Hello World {/* Error! */}
</View>
);
}
// ✅ Correct: wrap text in <Text>
import { View, Text } from "react-native";
export default function App() {
return (
<View>
<Text>Hello World</Text> {/* OK */}
</View>
);
}Solution:
- Always wrap text strings in
<Text>components - When prompting Rork AI to generate code, emphasize "React Native requires
<Text>for all text content"
3. Error: Rendered more hooks than during the previous render
Symptom: After user interaction, the console shows Error: Rendered more hooks than during the previous render.
Root Cause: Violating the React Hooks rules. The two most common patterns:
- Calling Hooks inside conditions —
if (condition) { useState(...) }is forbidden - Calling Hooks in loops —
items.map(() => useEffect(...))is forbidden
// ❌ Wrong: useState inside a conditional
import { useState } from "react";
import { View, Button, Text } from "react-native";
export default function Counter() {
const [isEnabled, setIsEnabled] = useState(false);
// ❌ Calling useState inside if changes the number of hooks
if (isEnabled) {
const [count, setCount] = useState(0);
}
return (
<View>
<Button title="Enable" onPress={() => setIsEnabled(!isEnabled)} />
</View>
);
}
// ✅ Correct: all Hooks at component top level
export default function Counter() {
const [isEnabled, setIsEnabled] = useState(false);
const [count, setCount] = useState(0); // Top level always
return (
<View>
<Button title="Enable" onPress={() => setIsEnabled(!isEnabled)} />
{isEnabled && <Text>Count: {count}</Text>}
</View>
);
}Solution:
- The Hooks Rule: Always call Hooks at the top level of your component (never inside conditions, loops, or nested functions)
- This applies to all Hooks:
useState,useEffect,useCallback, etc.
4. Module not found / Cannot resolve module
Symptom: During build or app startup, you see Module not found: Can't resolve 'react-native-gesture-handler'.
Root Cause: Attempting to import a package that isn't installed, or version mismatch with dependencies.
// ❌ Importing a package that wasn't installed
import { GestureHandlerRootView } from "react-native-gesture-handler"; // Not installed
// ✅ Solution: install the package first
// $ npm install react-native-gesture-handler expo-gesture-handlerSolution:
- Install the package:
npm install {package-name} - If already installed, reinstall dependencies:
npm install - Check React Native/Expo version compatibility against the official matrix
- Clear Expo cache:
npx expo start --clear
5. White Screen of Death — Implementing an Error Boundary
Symptom: The app launches but displays a completely blank white screen. No error messages in the console.
Root Cause: A JavaScript error occurred, but error handling is missing, so nothing is shown to the user.
Solution: Implement an Error Boundary component to catch and display errors gracefully.
// 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;
}
// Error Boundary catches errors from child components and displays them
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 }}>
⚠️ An error occurred
</Text>
<Text style={{ fontSize: 14, color: "#666", marginBottom: 10 }}>
{this.state.error?.message || "Unknown error"}
</Text>
<Text style={{ fontSize: 12, color: "#999", fontFamily: "monospace" }}>
{this.state.error?.stack}
</Text>
</ScrollView>
);
}
return this.props.children;
}
}Usage:
// App.tsx
import { ErrorBoundary } from "./components/ErrorBoundary";
export default function App() {
return (
<ErrorBoundary>
<YourMainApp />
</ErrorBoundary>
);
}Now the app displays the error instead of crashing silently.
How to Read Rork Error Logs
The first step to solving any error is knowing where to look. Understanding error message structure is key.
Console Message Hierarchy
- Blue messages — Debug info (safe to ignore)
- Yellow messages — Warnings (improvement recommended)
- Red messages — Errors (must fix)
How to Read Error Messages Effectively
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)
Breaking this down:
- What happened? → Text strings must be rendered within a Text component
- Where? → MyComponent
- File location? → screens/HomeScreen.tsx, line 25
Read from top to bottom to pinpoint the exact issue and location.
Using the Fix Now Auto-Debug Feature
Rork's Fix Now feature can automatically fix many runtime errors detected by the AI.
- Screenshot the error and copy it
- Paste it into Rork chat and click "Fix Now"
- AI generates a fix and auto-applies it to your code
After Fix Now succeeds, always review and understand the fix—this knowledge helps you avoid the same error pattern in the future.
Expo Go vs Development Build
Expo Go (preview app) and Development Build (custom-built app) can behave differently when encountering errors.
- Expo Go runs without native modules (camera, location, etc.), so code using those won't work
- Development Build includes all native modules, closer to production
- Always test in both to catch platform-specific issues
A working Expo Go app isn't guaranteed to work in a Development Build, so test thoroughly.
Real Device Debugging with Rork Companion
Rork Companion (Mac app) makes debugging on actual devices much easier:
- Live log viewer — See device console output in real-time
- Hot reload — Auto-refresh when code changes
- Multi-device testing — Test simultaneously on multiple phones
For detailed instructions, see "Rork Companion Mac App".
Looking back
React Native and Expo runtime errors in Rork-generated apps follow predictable patterns. Once you've learned to recognize and fix them, you'll solve them quickly.
- State initialization — Always provide sensible default values
- Text component — Wrap all text strings in
<Text> - Hooks rules — Call Hooks only at component top level
- Module compatibility — Check versions and reinstall dependencies
- Error boundary — Use it to prevent white screen crashes
Master these patterns, and you'll develop Rork apps with confidence.
Reference
Helpful book for your development toolkit: