Mobile
React Native
One React codebase, real native iOS and Android apps — built by engineers who ship to both stores and keep them running.
Overview
React Native builds genuinely native iOS and Android apps from a single codebase written in React — JavaScript or, as we always write it, TypeScript. The word that matters is native: unlike a web view wrapped in an app shell, and unlike Flutter which draws every pixel with its own rendering engine, React Native maps your components onto the platform’s real native UI widgets. A list is a real UIKit or Android list, a switch is the real platform switch, and the result scrolls, animates and behaves the way each operating system expects because it is, underneath, the operating system’s own controls. You describe the interface in React; React Native realises it in native views.
For years this worked through a bridge — a layer that passed serialised messages asynchronously between the JavaScript thread and the native side. It was the source of React Native’s reputation for animation jank and slow start-up, because every interaction had to be marshalled across that boundary. The New Architecture has largely replaced it: JSI (the JavaScript Interface) lets JavaScript hold direct references to native objects and call them synchronously, the Fabric renderer rebuilds the UI layer on top of JSI, and TurboModules load native modules lazily and talk to them without the old serialisation cost. This is not cosmetic — it is the difference between a framework you had to apologise for and one we recommend without hedging for most apps.
We reach for React Native when a product needs to be on both iOS and Android, the team already thinks in React, and the app is a mainstream product rather than a graphics engine or a platform-integration showcase. In practice that is a large share of the apps businesses actually build — content, commerce, accounts, booking, internal tools, social features. We build these with Expo where it fits, because its managed workflow, EAS build and update pipeline, and over-the-air updates remove weeks of setup and let us ship fixes without waiting on an App Store review. Where a project needs to drop to native code, we do that too — and we are blunt, up front, about the cases where React Native is the wrong tool entirely.
Best for — Cross-platform iOS and Android apps for mainstream products, where sharing one React codebase — and one team’s React skills — matters more than squeezing out the last few per cent of native performance.
Why teams choose React Native
Two platforms, one codebase
Real native iOS and Android apps from a single React/TypeScript codebase. You write features once, ship them to both stores, and maintain one codebase instead of two — the largest single saving React Native offers over parallel native builds.
Real native UI, not a facsimile
Because your components render to the platform’s own native widgets, the app feels like it belongs on the device — native scrolling, gestures, accessibility and platform conventions — rather than a drawn-on-canvas approximation that users can sense is not quite right.
Your React team is your mobile team
The component model, hooks and data flow are the same as React on the web. Engineers move between web and mobile without a rewrite of skills, patterns and often logic — a real advantage if you already own a React web product.
Why businesses choose React Native
- You are committed to both iOS and Android and want to build and maintain them as one product rather than funding two separate native teams.
- You have — or want to build on — React skills, and value being able to move people and code between web and mobile.
- You want to iterate quickly and ship fixes to users fast, and Expo’s tooling and over-the-air updates are worth real money to your release cadence.
- Your app is a mainstream product where a genuinely native feel matters, but the last few per cent of raw performance does not.
What we build with React Native
The capabilities this technology is genuinely strong at — and what we most often build with it.
The New Architecture — JSI, Fabric, TurboModules
We build on and, where needed, migrate projects to the New Architecture: JSI for direct, synchronous JavaScript-to-native calls, the Fabric renderer for a faster and more consistent UI layer, and TurboModules for lazily loaded native modules. This is the machinery that removed the old bridge’s cost, and knowing it is how we diagnose and fix the performance problems that made React Native’s reputation.
Native component rendering
Your React components map to real native views — UIKit on iOS, the Android view system on the other side. We work fluently across that boundary, so an app uses genuine platform controls and honours each platform’s conventions rather than presenting one flattened design that feels foreign on both.
Expo managed workflow and EAS
Where it fits — and for most apps it does — we use Expo’s managed workflow, EAS Build for cloud builds without maintaining native toolchains, and EAS Submit for the store pipeline. It removes weeks of setup and a whole class of build-environment problems, and we know precisely when a project has outgrown it and needs the bare workflow.
Over-the-air updates
With EAS Update we ship JavaScript and asset changes straight to installed apps, so bug fixes and small features reach users in hours instead of days-long store reviews. We use this within the store rules — for JavaScript changes, not to smuggle past native review — and set it up so releases stay auditable and reversible.
Native modules and bridging
When a feature needs platform code with no maintained library, we write the native module ourselves in Swift or Kotlin and expose it cleanly to the JavaScript side. That ability is what keeps React Native from hitting a wall: a JavaScript-first codebase that can still reach anything the platform offers when it has to.
Hot reload and a fast inner loop
Fast Refresh keeps component state while code updates in place, so the edit-see-result loop is measured in seconds. Combined with TypeScript across the codebase and shared logic with any React web app you run, it makes day-to-day development quick and the code safe to change.
Use cases
Consumer apps on both stores
Content, commerce, social and account-based products that need to be on iOS and Android at once, where a single React team shipping to both is far cheaper than two native builds and the app is not pushing the hardware.
Companion apps to a React web product
A business already running a React or Next.js web app that wants a mobile presence sharing skills, patterns, API clients and non-visual logic — the case where React Native’s web overlap pays for itself most directly.
Internal and field tools
Staff-facing apps — inspections, logistics, point of sale, data capture — where reach across the devices employees actually carry matters more than bleeding-edge platform features, and fast iteration via over-the-air updates is a genuine advantage.
MVPs and market tests
Early-stage products that need to reach both platforms quickly on a limited budget, where Expo and EAS get a credible app in front of users fast and the architecture leaves room to drop to native code later if the product demands it.
When React Native is the right choice
- You need both iOS and Android from one codebase and one budget, and the app is a mainstream product — content, commerce, accounts, booking, internal tools — rather than something pushing the hardware. This is React Native’s home ground, and it roughly halves the app-layer work versus two native builds.
- Your team already writes React for the web. React Native shares the same component model, hooks and mental model, so web engineers become mobile engineers without relearning everything, and a fair amount of non-visual logic — validation, formatting, API clients, state — moves across directly.
- You want to ship fast and iterate faster: Expo’s managed workflow and EAS remove build-tooling pain, and over-the-air updates let you push JavaScript fixes to users in hours rather than waiting days for store review.
- Wrong for: performance-critical or graphics-heavy apps — real-time games, heavy 3D, intensive on-device media or computer vision — where a native or purpose-built engine will always beat a JavaScript-driven UI, even on the New Architecture.
- Wrong for: apps built around bleeding-edge, platform-specific capabilities the day they ship, or teams with no React skill to leverage. If you need the newest OS APIs first and have native engineers already, native Swift and Kotlin are the honest choice — and we will say so before you commit.
React Native: pros and cons
Strengths
- Genuinely native UI from one codebase — you ship real platform controls to iOS and Android, not a web view or a self-drawn approximation.
- Shares React’s model and much of its ecosystem, so a web React team is productive in mobile quickly and logic transfers across surfaces.
- Fast iteration: hot reload while developing, Expo and EAS to remove build pain, and over-the-air updates to ship JavaScript fixes without a store round-trip.
- The New Architecture — JSI, Fabric and TurboModules — has removed most of the old bridge-related performance friction that gave React Native its reputation for jank.
Trade-offs
- Historically the async JavaScript bridge caused performance friction on animation-heavy or computationally intensive screens; the New Architecture fixes most of it, but React Native still is not the tool for a genuine graphics engine.
- You still hit native code for some features — a capability with no maintained library means writing a native module in Swift or Kotlin, so a React skillset alone is not always enough.
- Upgrading between React Native versions can be genuinely painful, especially on projects that have ejected from Expo and carry native configuration and third-party native dependencies.
- It is not a substitute for fully native when you need the newest platform APIs on day one or the maximum performance a compiled native binary gives — for those, native Swift and Kotlin still win.
Architecture
A React Native app is a React tree running in a JavaScript engine, rendering to native views through the New Architecture’s renderer. We structure it much as we would a serious React web app — feature-based folders, a clear boundary between presentational and stateful components, server state handled by a caching layer such as TanStack Query, and only genuine client state placed in a store. On top of that sit the mobile-specific concerns: navigation (typically React Navigation or Expo Router), platform-specific code split cleanly where iOS and Android genuinely differ, and a considered position on where the line between JavaScript and native code falls.
That last decision is the one that defines the project. We keep as much as possible in TypeScript, where it is portable and fast to change, and drop to native modules only where a feature demands it — deliberately, and documented, rather than by accident. We also decide early whether a project lives in Expo’s managed workflow or the bare workflow, because that choice shapes the build pipeline, the update strategy and how painful future upgrades will be. Getting it right up front is cheap; discovering it was wrong two years in is not.
Performance
React Native’s performance story is mostly about two things: keeping the JavaScript thread free and not overworking the renderer. Historically the async bridge was the bottleneck, and animation-heavy screens paid for every trip across it. On the New Architecture, with JSI and Fabric, that cost is largely gone — but the discipline still matters. We profile rather than guess, using Flipper and the platform profilers, then apply the right fix: moving animations to the native driver or Reanimated so they run off the JavaScript thread, virtualising long lists, trimming unnecessary re-renders, and keeping heavy work off the main path.
We are also honest about the ceiling. For a mainstream app, a well-built React Native codebase on the New Architecture is indistinguishable from native to a user. For a real-time game, heavy 3D, or intensive on-device media processing, a JavaScript-driven UI will not match a native or purpose-built engine, and no amount of tuning closes that gap. Where that is your workload, we say so before you start rather than after you have paid for it.
Security
Mobile security starts from the assumption that the device is not trusted and the app binary can be inspected. Secrets never live in the JavaScript bundle, where anyone can extract them; authentication and authorisation are enforced server-side, and the app treats its own storage as readable by a determined attacker. We keep tokens and sensitive values in the platform’s secure storage — the iOS Keychain and Android Keystore — rather than in plain application storage, and we handle over-the-air updates carefully so the update channel itself cannot become an attack surface.
React Native’s large JavaScript dependency tree is real attack surface, and so is every native module a project pulls in. We keep dependencies lean and current, watch for known vulnerabilities, and pin native module versions deliberately. On the transport side we use certificate handling and network security configuration appropriate to the platform, and we treat deep links and any web views the app embeds as untrusted input that must be validated.
Scalability
For a client app, scaling is about the codebase and the team more than about request volume — the backend carries load, while the React Native app’s challenge is staying coherent as features, engineers and native dependencies multiply. Feature-based structure, a shared component library, typed contracts through TypeScript, and clear ownership of state are what let several engineers work in one app without it fragmenting. The mobile-specific risk is native dependencies: each one added is a future upgrade to manage, so we add them deliberately and keep the count honest.
The overlap with React on the web is where React Native scales beyond a single team. Shared API clients, validation, domain logic and even design tokens can live in a common layer that both web and mobile consume, so a growing product does not reimplement the same rules twice. We plan for the version-upgrade reality too — pinning, a tested upgrade path, and a preference for Expo’s managed workflow where it fits — because the projects that scale badly are almost always the ones that let upgrades slide until they became a rewrite.
React Native integrations & ecosystem
The technologies we most often pair with it — each links to how we work with it.
How we work
We settle the decisions that are cheap to get right early and expensive to change later: Expo managed workflow or bare, navigation strategy, where the JavaScript-to-native line falls, and how state and server data are handled. Then we build in thin vertical slices — a real feature, working on both iOS and Android, in the hands of testers — rather than a scaffold that demos well and does nothing. We write TypeScript throughout, share what genuinely can be shared with any React web codebase you run, and drop to native modules only where a feature truly needs it.
The engineers who design the app are the ones who write it, ship it to both stores and keep it running. That is what we mean by operating what we build: the trade-offs — including the version-upgrade cost and the point at which native code is unavoidable — are made by people who will live with them. You get honest advice on Expo versus bare, on React Native versus native versus Flutter, and an app your own team can pick up, upgrade and extend.
The service behind it
Delivered throughMobile App DevelopmentWhat we build with React Native
The disciplines this technology most often shows up in — from a first build to taking over and stabilising an existing one.
How we deliver
- 01
Discover
We map the system, the constraints and the business it serves — including the parts nobody documented.
Architecture brief
- 02
Architect
Decisions get made, written down and defended before a line of production code exists.
Decision records
- 03
Build
Short cycles against working software. You see progress in the product, not in a status deck.
Shipping increments
- 04
Operate
Monitoring, incident response and iteration. The system is alive, so the engagement is too.
Runbooks & SLOs
Industries we use React Native in
Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.
Also in Mobile
Why teams choose us for React Native
Senior engineers only
React Native rewards knowing the New Architecture, the native boundary and the upgrade traps — and punishes guesswork. The people making your decisions have shipped React Native apps to both stores and kept them running; there are no juniors learning on your project.
We operate what we build
We run the apps we ship, so we optimise for the eighteen-month reality — including the version upgrades and native-module maintenance vendors leave out of the pitch — not the demo. That means conservative choices and an app your team can actually maintain.
Honest about React Native versus the alternatives
If your app is graphics-heavy, needs the newest platform APIs first, or you have no React skill to build on, we will tell you native Swift and Kotlin — or Flutter — is the better call before you spend money, rather than sell you a React Native app you should not have built.
Typical timeline
- 01
Discovery and architecture
One to two weeks agreeing features, the Expo-versus-bare decision, navigation, state strategy and where native code will be required, so the foundations are settled before code volume grows.
- 02
First vertical slice
Two to three weeks delivering one real feature end to end on both iOS and Android, in testers’ hands, proving the architecture and the store pipeline against reality rather than a plan.
- 03
Iterative build
Feature-by-feature delivery in short cycles, each shippable to both stores, with performance profiled on real devices and accessibility checked as we go rather than bolted on later.
- 04
Store submission and handover
App Store and Play Store submission via EAS, over-the-air update channel set up and documented, test coverage on the load-bearing paths, and handover so your team can own, upgrade and extend the app.
How pricing works
- Fixed-scope builds for well-defined apps — a specific product for iOS and Android — quoted once we understand the features, integrations and where native code will be needed.
- Monthly senior engagement for ongoing product work across both platforms, where scope evolves and you want continuity and a maintained release cadence rather than a one-off deliverable.
- Focused audits and rescues for existing React Native codebases — performance problems, a stalled New Architecture migration, or a version upgrade that has stalled — priced by the assessment.
Hire React Native engineers
Need React Native capacity on your own team? We embed named senior engineers into your existing team — reporting to your leads, working in your rituals — so you add capacity without a hiring cycle.
Hire React Native engineersCommon questions
Does React Native really build native apps, or is it a web view?
Genuinely native. React Native maps your components onto the platform’s real native UI widgets — a list is a real native list, a switch is the real platform switch — so the app scrolls, animates and behaves like software that belongs on the device. This is different from a web view wrapped in an app shell, and different from Flutter, which draws its own pixels with its own rendering engine rather than using the platform’s controls.
React Native or Flutter — which should we choose?
It depends on your team and your app. React Native uses React with JavaScript or TypeScript and renders real native components, so it shares skills and code with any React web team you have — a decisive advantage if you already write React. Flutter uses Dart and its own renderer, which gives very consistent visuals and strong animation performance but shares nothing with a web React codebase. If you have React skills, React Native is usually the pragmatic choice; if visual consistency and animation are paramount and you have no React investment, Flutter is a fair alternative.
Is React Native still slow because of the bridge?
Much less than its reputation suggests. The old async bridge — which serialised every message between JavaScript and native and caused most of React Native’s animation jank — has largely been replaced by the New Architecture: JSI for direct, synchronous native calls, the Fabric renderer, and TurboModules. For a mainstream app on the New Architecture, users cannot tell it from native. The honest exception is genuinely performance-critical work — games, heavy 3D, intensive media — where a native or purpose-built engine still wins.
Should we use Expo, or does it hold us back?
For most apps we recommend Expo. Its managed workflow, EAS build and update pipeline, and over-the-air updates remove weeks of setup and a whole class of build-environment problems. The old objection — that you had to eject to use native code — is largely gone, since config plugins and development builds let you add native dependencies while staying in the managed flow. We know precisely when a project has genuinely outgrown Expo and needs the bare workflow, and we make that call deliberately rather than by default.
Will we ever need to write native iOS or Android code?
Sometimes, yes — and we build for it. Most features are served by the JavaScript ecosystem and maintained libraries, but when a capability has no library, or needs performance or platform access the JavaScript side cannot give, we write a native module in Swift or Kotlin and expose it cleanly to your React Native code. That ability is exactly what keeps React Native from hitting a wall: a JavaScript-first codebase that can still reach anything the platform offers when it has to.
Building on React Native?
A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.