Platform differences: why "write once, run anywhere" is only partially true
Lesson 1 promised React Native lets one codebase target iOS and Android together — true, and incomplete on its own. Two real operating systems, with real behavioral and design differences, sit underneath that one codebase, and pretending otherwise produces apps that feel subtly wrong on at least one platform.
Intermediate
2 min read
Platform.OS: branching on which operating system is actually running
Platform.OS returns "ios" or "android" at runtime, letting a single component branch its behavior or styling per platform — used constantly for exactly the kind of small, real difference shown above: status bar heights differ, shadow rendering works completely differently (iOS uses shadowColor/shadowOffset; Android uses elevation, an entirely different property with no direct equivalent), and default component appearances (a switch, a slider) look genuinely different by platform default, reflecting each platform's own native design language.
Platform-specific files: .ios.js / .android.js as an alternative to branching
Button.ios.js — iOS-specific implementation
Button.android.js — Android-specific implementation
import Button from "./Button"; // the bundler picks the RIGHT file automatically
For a component different enough between platforms that inline Platform.OS branches would become unwieldy, React Native's build tooling automatically resolves import Button from "./Button" to Button.ios.js or Button.android.js depending on the target platform — the same component name, two genuinely separate implementations, chosen automatically at build time rather than branched at runtime.
Why this is the correct response to real design-language differences, not just technical quirks
iOS and Android genuinely have different conventions for where navigation controls live, how modals present, what a "back" gesture does by default, and what users on each platform actually expect an app to feel like — UI/UX for Developers' own domain covered usability heuristics generally; this is that exact principle applied specifically to two platforms with real, divergent, well-established design languages (Apple's Human Interface Guidelines, Google's Material Design). An app that ignores these differences and looks pixel-identical on both platforms typically feels subtly "wrong" to users on whichever platform it wasn't originally designed around — platform-aware code isn't extra, avoidable complexity; it's what makes an app feel genuinely native on each one.
The real limit: "write once, adjust twice" is the honest summary
Business logic, data fetching, state management, and most of a real app's actual functionality genuinely is shared, unchanged, across platforms — this is React Native's real, substantial value. The UI layer specifically needs deliberate platform awareness in exactly the places lesson 5's styling differences and this lesson's behavioral differences actually show up — treating "cross-platform" as "identical on every platform" rather than "one shared codebase, platform-aware where it genuinely matters" is the actual source of apps that technically run everywhere but feel right nowhere.