Skip to content

React Native or native? How to decide for your app

One codebase for iOS and Android sounds like half the cost, and sometimes it is. How to decide between React Native and fully native apps for a specific app: what the app does, which device features it needs, what happens in the background, and what the second codebase really costs.

Almost every mobile project starts with the same question: should the app be built once, with a cross-platform framework such as React Native, or twice, natively for iOS and for Android?

The usual answers are either "cross-platform is half the cost" or "native is always better". Both are wrong often enough to be dangerous. The right answer depends on what the particular app does, and in my experience it can be found with a handful of questions. This article goes through them, including the case where the honest answer is both.

What the two options actually are

React Native lets you write the app once, in JavaScript or TypeScript, and run it on both iOS and Android. It does not draw a web page inside an app: the interface is made of the platform’s own native components, and the app’s logic runs in a JavaScript engine alongside them. When the app needs something the framework does not provide, it can call native code written for each platform.

Native development means two separate apps: one in Swift for iOS, one in Kotlin for Android, each using its platform’s tools and interface directly.

Both produce real apps from the stores. The difference is in what is easy, what is hard, and what you pay for over the years.

1. Is it mostly screens and data?

Most business apps are, at heart, screens and data: lists, forms, detail pages, a login, notifications, a sync with a server. For apps like that, React Native is usually the better choice. One codebase means one set of screens to build, one set of bugs to fix and one release to plan, and the result is indistinguishable to the user from a native app.

The balance shifts as the app leans on the device itself:

  • Bluetooth, especially talking to your own hardware
  • work that continues in the background, such as tracking, scanning or long uploads
  • heavy camera or video processing
  • widgets, watch apps, and deep integration with the operating system
  • graphics-heavy interfaces and games

None of these rules React Native out. Each one means more of the app lives in native code anyway, and the benefit of sharing the rest shrinks.

2. Which device features does it need?

This is where the decision is really made, and where general advice is least useful, because the details matter.

I built a Bluetooth asset-tracking app in React Native, with Expo on top. It scans for its own tags, keeps working in the background, uses location, the camera and push notifications, and ships updates over the air. It works, on both platforms, from one codebase, and it was the right choice for that app. But the Bluetooth scanning, the background work and the permissions around them took a disproportionate share of the effort, and a good part of that effort was platform-specific: iOS and Android have different rules for what an app may do when it is not on screen, and a shared codebase does not make those rules the same.

So the question is not "does React Native support Bluetooth?" It does, through well-maintained libraries. The question is how much of the app’s value lives in the device-specific part. If it is a small part of a large app, share the rest. If it is most of the app, the shared part may be too small to be worth the extra layer.

3. Does it have to be fast in a special way?

People often ask about performance first. For screens and data, a well-built React Native app is fast, and the gap to native is not something users notice. Where it can show is long, complex lists, heavy animations and anything that processes a lot of data on the device. Those can be made fast in React Native too, but they take more care.

If the app’s main job is performance-sensitive, a camera app, an editor, a game, that is a strong argument for native. If it is a business app, it usually is not.

4. What does it cost over time?

The cost comparison that matters is not the first version, it is the next five years:

  • Two native apps mean every feature is built twice, tested twice and released twice. The apps also drift apart over time, because nobody builds the same feature twice in exactly the same way.
  • One React Native app means one feature built once, but also one more layer that has to be kept up to date. Framework upgrades are a real, recurring cost, and skipping them makes each later upgrade harder.
  • The platforms change every year for both approaches. New operating system versions, new store rules, new minimum requirements for the build tools.

That last point is easy to underestimate. Each new version of Xcode raises the oldest iOS version it will build for, and every dependency in the app has to follow, or the build simply stops. Google Play raises its target requirements on a schedule of its own. None of that is in the app’s own code, and all of it is maintenance an app needs every year, whichever way it was built.

5. Who will maintain it?

Think about who will look after the app in three years. A React Native app needs someone comfortable with TypeScript and React, which is a large pool, plus occasional native knowledge. Two native apps need Swift and Kotlin skills, ideally in the same person or a team that talks to each other.

If your business already has web developers who work in React, React Native lets them contribute to the app. If you have native developers, the argument runs the other way.

The mixed approach

The choice is not all or nothing. A common and sensible shape is a React Native app for the screens and the data, with native modules for the parts that need the platform directly: a Bluetooth layer, a background service, a camera pipeline. The shared part stays shared; the platform-specific part is written for the platform.

That is also a safe place to start when you are unsure. If the device-specific part grows until it dominates the app, it can be moved to fully native one piece at a time.

What a modern React Native project looks like

Most new React Native projects today start with Expo, a set of tools and libraries on top of React Native. It handles much of the platform plumbing: building for both stores, over-the-air updates, and a large set of maintained modules for the camera, location, notifications and secure storage.

When an app needs native code Expo does not provide, it uses a development build: your own build of the app with your native modules included, still using Expo’s tools around it. Configuration that would otherwise mean editing the iOS and Android projects by hand is expressed as config plugins, so the native projects can be regenerated at any time. That last point matters more than it sounds: hand edits to generated native projects are lost the next time they are regenerated, and a fix that only lived in one of them quietly disappears.

Permissions, twice

Device features come with permissions, and the two platforms handle them differently. Bluetooth is a good example:

  • On iOS, the app must declare why it uses Bluetooth, and the system shows that sentence to the user when it asks.
  • On Android, recent versions split Bluetooth into separate permissions for scanning and for connecting, and older versions tie scanning to location permission.
  • Background use adds further declarations on both platforms, and the stores check that the app really needs them.

A cross-platform library smooths the code over, but the permission design, what to ask for, when, and what the app does when the answer is no, has to be thought through for each platform. That is a good example of why "one codebase" never quite means "one of everything".

Writing your own native module

Sooner or later, many apps need something no library provides, or provides badly. Then you write a native module: a small piece of Swift and Kotlin that does the platform-specific work and offers a simple interface to the rest of the app.

The skill is in keeping that interface small. "Start scanning for these devices, tell me when you see one" is a good native module. A module that leaks every platform detail into the shared code is not, because then the shared code has to understand both platforms anyway.

The web, from the same code

React Native code can also run in a web browser, through React Native for Web. The app I mentioned above has a web version from the same code, which makes a useful companion for people who work at a desk rather than on a phone.

It is not free: some screens need a different layout for a large screen, and device features such as Bluetooth scanning do not exist in the same form in a browser. But for the screens and data part of an app, sharing with the web can remove a third codebase.

Keeping it up to date

React Native and Expo release new versions several times a year. Upgrading is part of owning the app, and doing it regularly keeps each step small:

  1. Upgrade one version at a time, not three at once.
  2. Read the release notes for breaking changes, especially in native modules.
  3. Upgrade the libraries the app depends on alongside, since many follow the same schedule.
  4. Build and test on real devices on both platforms before releasing.

An app that skips upgrades for two years does not stay still. It falls behind the stores’ minimum requirements, and then has to catch up all at once, under deadline.

Testing a cross-platform app

The same testing ideas apply as anywhere else, with two additions for mobile. Unit tests cover the logic shared by both platforms, and they are where most of the value is. End-to-end tests on mobile are slower and harder to keep stable than on the web, so they are best kept to the few paths that matter most. And there is no substitute for trying a build on real phones, an older Android and a recent iPhone at least, before every release, because the things that break on mobile are often the things simulators do not simulate: Bluetooth, background behaviour, and permissions.

What it costs

People ask for a number, so it is worth being honest about why a general one does not exist. The cost of an app depends far more on what it does than on how it is built: the number of screens, the complexity of the data, the device features, the integrations with other systems, and how polished it needs to be on day one.

What can be said in general is where the difference between the approaches shows. For a screens-and-data app, building once rather than twice saves a large part of the interface work, and the saving continues with every feature added later. For an app dominated by device-specific work, the saving shrinks, because that work has to be done per platform anyway. The first version of an app is also rarely the expensive part: the years of changes after it are, which is where one codebase or two matters most.

Deciding for your app

If you are deciding for a specific app, write down answers to these, and the choice usually becomes clear:

  • Which platforms, now and in two years?
  • Which device features, and how central is each to the app’s value?
  • Does anything need to happen while the app is closed?
  • Who will maintain it, and what do they know?
  • Is there also a web version, now or later?

If the answers still point both ways, start with React Native and a native module for the demanding part. It is the option that is easiest to move away from later, in either direction.

a rough guide
  • Mostly screens and data, both platforms needed, a team that knows React: React Native.
  • The app is its hardware integration, or its camera, or its graphics: native.
  • A business app with one demanding feature: React Native with a native module for that feature.
  • Only one platform needed, now and later: native for that platform, with no extra layer.

Whichever it is, the store accounts and the signing keys should be in your name from day one. That is covered in Getting your app through App Store and Google Play review.

Planning an app?

Tell me what it has to do, and which devices it has to talk to.

Discuss your project