React Native: What 'Learn Once, Write Anywhere' Really Means

The single most useful thing to get straight about React Native is a slogan, and it's one people consistently misquote. The promise was never "write once, run anywhere." It was "learn once, write anywhere" — and the difference between those two words is the entire reason web developers either love React Native or feel betrayed by it.
Because here's what actually transfers to mobile: your React knowledge. Components, props, state, hooks, the mental model of describing UI as a function of data — all of it, intact, on day one. You are not starting over. What does not transfer is a lot of your code and, more subtly, a lot of your instincts. The <div> you've typed a hundred thousand times doesn't exist. CSS as you know it doesn't exist. The layout habits your fingers have memorized quietly stop working. So you arrive on mobile fluent in the language and unfamiliar with the streets, and whether that feels empowering or frustrating comes down entirely to expecting it.
This article is about drawing that line honestly — what your React experience genuinely buys you on mobile, and where it stops — so you show up expecting "learn once," not "write once," and don't waste a week being angry at the wall.
There Is No DOM. That's the Whole Shift.
Start with the concept that reorganizes everything else: React Native does not render to a browser, because there is no browser. Your components render to actual native platform views — a real iOS UIView, a real Android widget. React is the engine describing the UI; the thing it draws is native, not HTML.
This is why the primitives change. You don't write <div> and <span> and <p>, because those are HTML and there's no HTML here. You write <View> and <Text>, which map to genuine native components:
import { View, Text, Pressable } from 'react-native'; export function Greeting({ name }: { name: string }) { return ( <View style={styles.card}> <Text style={styles.title}>Hi {name}</Text> <Pressable onPress={() => console.log('tapped')}> <Text>Tap me</Text> </Pressable> </View> ); }
Notice how familiar the shape is — it's components, props, a style prop, an event handler. And notice how many small things are different: View not div, Text wrapping every piece of text (you can't just drop a bare string like in HTML), onPress not onClick, Pressable instead of a button. That's "learn once, write anywhere" in miniature — the shape of your React knowledge fits perfectly, and every specific has to be relearned. The engine is the same; the vocabulary is new.
Styling: It Looks Like CSS and Isn't
The place this bites hardest, and the one worth dwelling on, is styling — because it looks close enough to CSS that you trust it, then it violates that trust.
React Native styling resembles CSS: you write style objects with camelCased properties, and many familiar names work. But it is not CSS, and the differences are exactly the ones your instincts will trip over. There are no cascading stylesheets, no selectors, no inheritance in the way you rely on — styles are explicit, per-component objects. There's no display: block versus inline. Most jarring of all: everything is flexbox, and it's vertical by default. On the web, flexDirection defaults to row; in React Native it defaults to column, because a phone screen is tall. Your web layout muscle memory, built on horizontal-by-default flow, is subtly wrong on every screen until you internalize the flip.
import { StyleSheet } from 'react-native'; const styles = StyleSheet.create({ card: { // flexDirection defaults to 'column' here — the opposite of the web. padding: 16, backgroundColor: '#fff', }, title: { fontSize: 18, fontWeight: '600' }, });
None of this is hard. It's just different, and the danger is precisely that it looks similar enough that you don't respect the difference and spend an afternoon confused why your row is a column. Expect styling to be "CSS-flavored, not CSS," and the friction drops away. Treat it as the CSS you know and it will quietly punish you.
Just Use Expo
A practical fork, stated plainly because it saves the most pain: when you start a React Native project, use Expo. Bare React Native drops you into native build toolchains — Xcode, Android Studio, native dependency management — which is a heavy, platform-specific world that has nothing to do with React and everything to do with mobile plumbing you didn't sign up to learn on day one.
Expo is to React Native roughly what a good meta-framework is to React on the web: it owns the miserable setup and configuration so you can stay in the part you're good at. It handles the build tooling, gives you a clean managed workflow, and bundles access to native device APIs — camera, location, notifications — behind simple JavaScript, so reaching for the camera doesn't mean touching native code. It's the same lesson this whole series keeps landing on: don't hand-assemble the plumbing when a well-made tool already owns it. For the overwhelming majority of apps, Expo is simply the right starting point, and starting bare is a choice you should have a specific reason for.
The Instinct That Actually Needs Retraining
Beyond the vocabulary, there's a deeper adjustment, and it's the one that separates a web app running on a phone from an app that belongs there. Mobile is not a small desktop, and users can feel the difference instantly.
Touch is not a mouse. There's no hover — a whole category of web interaction just doesn't exist, and designs that lean on it fall flat. Targets have to be finger-sized, not cursor-precise. Gestures — swipe, long-press, pull-to-refresh — are expected vocabulary, not enhancements. Platform conventions differ, and iOS and Android users each have expectations about how navigation and controls should feel that a lowest-common-denominator layout ignores at its peril. And the device itself imposes realities the desktop rarely forces you to think about: constrained screens, variable network, battery, memory. The web developer's instinct to fill horizontal space, to treat the network as reliable, to assume hover and precise pointing — those instincts need retraining, and the app quality lives in that retraining far more than in the syntax.
This is the honest edge of "learn once, write anywhere": your React transfers, but your sense of what a good interface is has to expand from the web's assumptions to the phone's. That's not a knock on React Native — it's the reality of the platform being genuinely native, which is the whole point of using it.
How I'd Approach It
Strip it to decisions:
- It's "learn once," not "write once." Your React knowledge transfers whole; a lot of your code and instincts don't. Expect that and the wall becomes a curriculum.
- There is no DOM.
ViewandText, notdivandspan;onPress, notonClick. You render to real native views. - Styling is CSS-flavored, not CSS. No cascade, no selectors, flexbox everywhere, and column-by-default. Respect the difference instead of trusting the resemblance.
- Use Expo. It owns the native build plumbing so you stay in React. Go bare only with a specific reason.
- Retrain your interface instincts. Touch, gestures, finger targets, platform conventions, device limits — mobile is native, not a narrow desktop.
The reason React Native either delights or frustrates comes down to which promise you showed up believing. Arrive expecting "write once, run everywhere" and every difference feels like a broken promise. Arrive expecting "learn once, write anywhere" and the exact same differences feel like a reasonable tax on real native rendering — you keep the expensive thing, your React fluency, and pay for the platform specifics, which is a genuinely good trade. The knowledge is the asset. The code was always going to be somewhat local to where it runs.
For the final article, the series leaves flat screens behind completely: React in VR and AR — where the same component model gets pointed at three-dimensional space, and what it means to write <mesh> instead of <div>.
If you're a web developer eyeing your first React Native project and bracing for a total restart, don't — it's far more transfer than restart, once you know which parts are which. Tell me what your app needs to do on the phone and I'll tell you where your web instincts will help and where they'll trip you.