Module Overview
- Expo vs React Native CLI decision
- Node.js and package manager setup
- iOS development setup (macOS only)
- Android development setup (all platforms)
- VS Code configuration
- Troubleshooting common issues
Expo vs React Native CLI
Before setting up, choose your development approach. This is one of the most consequential decisions in a React Native project, and it is not as binary as it once was. Expo has evolved from “the training wheels option” to a production-grade toolchain used by companies like Shopify and Discord. The bare CLI remains necessary for brownfield integrations (adding React Native screens to an existing Swift/Kotlin app) and for teams that need full control over native build configuration.- Choose Expo If
- Choose CLI If
- You’re learning React Native
- Building a new project from scratch
- Don’t need custom native modules (yet)
- Want faster development iteration
- Need to build iOS apps on Windows/Linux
- Want managed OTA updates
Prerequisites (All Platforms)
1. Install Node.js
React Native requires Node.js 18 or newer. Node is the JavaScript runtime that powers Metro (the bundler), the development server, and all the CLI tooling. It does not run on the device itself — Hermes or JavaScriptCore handles that. Think of Node as the backstage crew: essential during development, invisible in production.- macOS
- Windows
- Linux
2. Install a Package Manager
- npm (Default)
- Yarn
- pnpm (Fastest)
3. Install Git
- macOS
- Windows
- Linux
Expo Setup
Quick Start with Expo
Install Expo Go
Download Expo Go on your physical device:iOS
Android
Running Your App
Expo Development Builds
For native modules not in Expo Go, create a development build:iOS Setup (macOS Only)
1. Install Xcode
- macOS Ventura 13.5 or later (for Xcode 15)
- ~25GB free disk space
- Apple ID (free)
2. Install Xcode Command Line Tools
3. Install CocoaPods
CocoaPods is the dependency manager for iOS native dependencies — it is to iOS what Gradle is to Android. Every time you install a React Native library that includes native iOS code (camera, maps, push notifications), CocoaPods links those native modules into your Xcode project. If you skippod install after adding a library, the JavaScript side will try to call native code that does not exist, resulting in a “module not found” crash at runtime.
4. Install iOS Simulator
5. Install Watchman (Recommended)
Watchman improves file watching performance:iOS Setup Verification
Android Setup (All Platforms)
1. Install Java Development Kit (JDK)
React Native requires JDK 17. Android builds use Gradle, which compiles your Java/Kotlin native code and packages the JavaScript bundle into an APK or AAB. The JDK version must match what Gradle expects — using JDK 11 or JDK 21 instead of 17 will produce cryptic build failures. This is one of the most common Android setup pitfalls: the version mismatch error messages rarely tell you “wrong JDK version” directly.- macOS
- Windows
- Linux
2. Install Android Studio
Download Android Studio from developer.android.com/studio During installation, ensure these are selected:- Android SDK
- Android SDK Platform
- Android Virtual Device (AVD)
3. Configure Android SDK
4. Set Environment Variables
- macOS/Linux
- Windows
~/.zshrc or ~/.bashrc:5. Create Android Virtual Device (AVD)
The Android emulator simulates a physical Android device on your computer. Unlike the iOS Simulator (which runs native ARM code directly on Apple Silicon), the Android emulator actually emulates ARM hardware, which is why hardware acceleration (Hyper-V on Windows, KVM on Linux, Hypervisor.framework on macOS) is critical for performance. Without hardware acceleration, the emulator can be 10-50x slower. A practical tip: choose a recent Pixel device image with Google Play services if you need to test Google Maps, Google Sign-In, or push notifications. System images without Google APIs will not have these services available.6. Enable Hardware Acceleration
- macOS
- Windows
- Linux
Android Setup Verification
VS Code Setup
Install VS Code
Download from code.visualstudio.comEssential Extensions
These extensions transform VS Code into a capable React Native IDE. The React Native Tools extension gives you inline debugging, and the Expo Tools extension provides autocomplete forapp.json configuration (where a single typo can cause silent build failures).
VS Code Settings
Launch Configuration
Physical Device Setup
iOS Physical Device
Android Physical Device
Wireless Debugging (Android 11+)
Troubleshooting
Common Issues
'react-native' command not found
'react-native' command not found
iOS: 'pod install' fails
iOS: 'pod install' fails
Android: 'SDK location not found'
Android: 'SDK location not found'
Android: 'INSTALL_FAILED_INSUFFICIENT_STORAGE'
Android: 'INSTALL_FAILED_INSUFFICIENT_STORAGE'
Metro bundler port in use
Metro bundler port in use
'Unable to load script' error
'Unable to load script' error
Xcode build fails with signing error
Xcode build fails with signing error
Clean Build Commands
Environment Verification Script
Create a script to verify your setup:Quick Reference
Essential Commands
Mobile Dev Setup Pitfalls
Next Steps
Module 3: Project Structure
Interview Deep-Dive
A new developer on your team is on Windows and needs to develop and test iOS builds. What are their options?
A new developer on your team is on Windows and needs to develop and test iOS builds. What are their options?
- They cannot run Xcode or iOS simulators on Windows — Apple restricts those to macOS. But they have three viable options. First, EAS Build runs iOS builds in the cloud on Apple silicon machines. The developer writes code on Windows, pushes to a branch, and EAS compiles the iOS build remotely.
- Second, for on-device testing during development, they can use Expo Go on a physical iPhone. They run
npx expo starton Windows, scan the QR code, and Expo Go loads the JS bundle over the network. - Third, for native debugging they can use cloud Mac services (MacStadium, AWS EC2 Mac instances) or pair with a macOS-using teammate for iOS-specific issues.
- What I would not recommend: Hackintosh setups or assuming “it will work on iOS too” based on Android-only testing. Platform differences in keyboard handling, safe areas, and gesture navigation will surface in production.
- The number one cause is missing hardware acceleration. Check if Hyper-V or HAXM is enabled via
systeminfoin PowerShell. If “Virtualization Enabled in Firmware” says No, they need to enable VT-x (Intel) or SVM (AMD) in BIOS. - Second: verify the system image architecture. Use x86_64 images on Intel hosts and arm64-v8a on ARM-based Windows. Mismatched architectures force software emulation, which is 10-50x slower.
- Third: allocate at least 2GB RAM and 2 CPU cores in AVD Manager, and enable GPU acceleration (Hardware GLES 2.0).
- If all else fails, use a physical Android device via USB. It is faster, shows real-world performance, and avoids emulator configuration entirely.
Explain the role of CocoaPods in React Native iOS builds. What happens when pod install fails?
Explain the role of CocoaPods in React Native iOS builds. What happens when pod install fails?
- CocoaPods is the dependency manager for iOS, analogous to npm for JavaScript. Running
pod installreads thePodfile, resolves version constraints, downloads native dependency source code, and generates an Xcode workspace that links everything. React Native itself is a CocoaPod, along with every native module. - Debugging failures depends on the error. “CDN: trunk URL could not be downloaded”: run
pod repo update. “Specs satisfying dependency were not found”: a version conflict — checkPodfile.lockfor pins. “No podspec found for library”: the RN library was not properly linked — ensurenpx pod-installran afternpm install. - The nuclear option:
cd ios && rm -rf Pods Podfile.lock build && pod cache clean --all && pod install --repo-update. This clears all cached state and rebuilds from scratch. - Critical production practice: commit
Podfile.lockto version control. Without it, different team members resolve different dependency versions, causing “works on my machine” failures. Treat it likepackage-lock.json.
- The Xcode project sandbox does not match the committed
Podfile.lock. Someone updated a pod locally but CI has a stalePods/cache. - Fix: ensure CI runs
cd ios && pod installafternpm ciand before the Xcode build. Do not cachePods/without also keying onPodfile.lock. - Preventive measure: use
pod install --deploymentin CI, which fails ifPodfilewas modified without updatingPodfile.lock, catching desync issues early.
Your team uses Expo but needs to integrate a native SDK that modifies MainApplication.java. What are your options without ejecting?
Your team uses Expo but needs to integrate a native SDK that modifies MainApplication.java. What are your options without ejecting?
- First, check if an Expo config plugin already exists for the SDK. Config plugins modify native files (AndroidManifest, MainApplication, Info.plist) at build time without maintaining native code in your repository.
- If no plugin exists, write a custom config plugin — a JavaScript function that receives the Expo config and returns modified native configuration. This is the modern replacement for ejecting.
- If the SDK requires runtime native code, create a local Expo module using
expo-modules-core. Write Swift/Kotlin that integrates with the Expo module system while keeping the managed workflow. - As a last resort, switch to development builds (
npx expo run:android) which gives you theandroid/directory while still using Expo’s module system. This is not ejecting — you retain EAS Build and EAS Update support.
- EAS Build runs in a clean environment, so the failure likely involves environment differences. First, check the EAS Build logs for the exact error (they are available in the Expo dashboard).
- Common causes: the config plugin references a local file path that does not exist in CI, or it depends on an environment variable not set in EAS secrets. Use
eas build --localto reproduce the cloud build environment locally. - Add
console.logstatements in your config plugin — they appear in the build logs. Use thewithDangerousModmodifier to inspect the generated native files mid-build and verify your modifications are applied correctly.