How to buildOctober 11, 20269 min read
React Native + ExpoStep 1 of 9

Mobile development: native, React Native or Flutter

In short

Native development means two separate apps: Kotlin with Jetpack Compose for Android and Swift with SwiftUI for iOS, with full access to every platform API. React Native (usually together with Expo) lets you write one app in TypeScript using the React model, while the screen shows real native components. Flutter also gives you one codebase, but in Dart, and draws the UI with its own engine; the choice between them depends on the device APIs you need, your team and how much platform code you are willing to maintain.

ComparisonLevel: BeginnerMobile Fundamentals

After this you will be able to

  • Compare Kotlin/Compose, Swift/SwiftUI, React Native with Expo and Flutter by language, how the UI is rendered, device API access and shared code
  • Explain why React Native is not “a website in a wrapper” and how its View and Text components differ from <div> and <p>
  • Walk through the decision tree and justify a stack choice for given requirements and a team
  • List the build and publishing steps shared by all stacks, including iOS builds and storing signing keys
Contents
  1. 01First: do you need an app-store app at all
  2. 02Native: Kotlin with Compose and Swift with SwiftUI
  3. 03React Native and Expo: the React model and native components
  4. 04Flutter and Dart: its own rendering engine
  5. 05Comparison by engineering criteria
  6. 06Builds and publishing: what every stack shares
  7. 07How to choose: a decision tree

First: do you need an app-store app at all

Before comparing frameworks, check whether you need an installable app at all. MDN defines a PWA (progressive web app) as an app built with web technologies that runs on many platforms from a single codebase, can be installed on the device, works offline and integrates with the system. If your scenario fits within what the browser can do, a PWA is simpler to ship and update. We covered the business side of this choice — store review, acquisition channels, phasing — in “PWA or mobile app”; here is the engineering angle: what actually changes in code, tooling and team.

Engineering signs that the web will not be enough: the app has to live in the App Store and Google Play; you need APIs the browser does not expose, or exposes with limits on a particular platform; background work matters, as does tight system integration (widgets, sharing, biometrics, platform payments); you need a smooth, complex interface with gestures and animation on low-end devices.

Native: Kotlin with Compose and Swift with SwiftUI

A native app is written in the platform’s main language with the platform’s own tools. For Android that is Kotlin: since 2019 Google has developed the platform Kotlin-first and recommends starting new apps with it, while keeping Java support. The UI is built with Jetpack Compose, which the Android documentation calls the recommended modern toolkit for native UI: you describe the interface, and Compose updates it when the state changes. The IDE is Android Studio.

For iOS it is Swift and SwiftUI — Apple’s declarative framework for all of its platforms, with live previews in Xcode. SwiftUI can be adopted incrementally next to the older UIKit. Xcode is Apple’s toolset for developing, testing and distributing apps, and it runs on a Mac.

Strengths

  • New system APIs are available immediately, with no wait for framework wrappers
  • UI and behaviour match the platform exactly
  • Official documentation, samples and profiling tools come from the OS vendor

Cost

  • Two apps, two languages, two codebases — every feature is built twice
  • You need developers for each platform, or people who know both
  • Keeping behaviour and releases of two versions in sync is extra work

A middle ground is Kotlin Multiplatform. Google officially supports it for sharing business logic between Android and iOS, and JetBrains’ Compose Multiplatform lets you share the UI too if you want. It suits a team that already writes Kotlin and wants to stop duplicating logic without giving up native UI.

React Native and Expo: the React model and native components

React Native lets you write a mobile app in JavaScript or TypeScript using the same model as React: components, props, state, hooks. The fundamental difference from the web is that there is no DOM and no HTML. Instead of <div> and <p> you use the View and Text components, and at runtime React Native creates real Android and iOS views for them. It is not a website in a wrapper: the screen shows system UI elements.

View

Android
ViewGroup
iOS
UIView
Closest web analogue
non-scrolling <div>

Text

Android
TextView
iOS
UITextView
Closest web analogue
<p>

Image

Android
ImageView
iOS
UIImageView
Closest web analogue
<img>

ScrollView

Android
ScrollView
iOS
UIScrollView
Closest web analogue
scrolling <div>

TextInput

Android
EditText
iOS
UITextField
Closest web analogue
<input type="text">
How React Native core components map to the platforms (per the React Native docs)

Since version 0.76, React Native enables the New Architecture by default: the asynchronous “bridge” between JavaScript and native code is replaced by JSI (JavaScript Interface) — direct calls without serialising data. It also supports the concurrent features of React 18 and later. The documentation is upfront that the New Architecture alone does not guarantee a speed-up: the gain depends on your app’s code.

The React Native team itself recommends starting new apps with a framework, and names Expo first: it provides file-based routing, a standard library of native modules and plugins that change native code without hand-editing the Android and iOS projects. At the time of checking, the current release is Expo SDK 57, built on React Native 0.86 and React 19.2.

Flutter and Dart: its own rendering engine

Flutter solves the same “one codebase, two platforms” problem differently. Instead of system UI elements it draws everything itself: Flutter has its own Dart implementation of every control, including counterparts of the iOS and Android switches. Rendering is done by a C++ engine with the Impeller renderer, which ships with the app; on iOS Impeller is the only supported renderer, and on Android it is enabled by default from API 29.

The code is written in Dart. During development the app runs in a virtual machine with hot reload — changes appear without a full rebuild and without losing state. For release, Flutter compiles the code directly to machine instructions. Flutter reaches platform APIs through platform channels — a message channel between Dart and native code — or through FFI for C libraries.

Comparison by engineering criteria

Language

Native (Kotlin / Swift)
Kotlin and Swift — two languages
React Native + Expo
TypeScript / JavaScript
Flutter
Dart

How the UI appears

Native (Kotlin / Swift)
System frameworks: Compose, SwiftUI
React Native + Expo
React components → native platform views
Flutter
Its own widgets, drawn by the Impeller engine

Shared Android/iOS code

Native (Kotlin / Swift)
None (or logic via Kotlin Multiplatform)
React Native + Expo
Most of the app
Flutter
Most of the app

New system APIs

Native (Kotlin / Swift)
As soon as the SDK ships
React Native + Expo
Via Expo and community modules or your own native module
Flutter
Via plugins or your own platform-channel code

Development loop

Native (Kotlin / Swift)
Build and previews in Android Studio / Xcode
React Native + Expo
Fast code refresh via Metro, Expo Go
Flutter
Hot reload in the Dart VM

Web from the same code

Native (Kotlin / Swift)
No
React Native + Expo
Yes, via React Native for Web in Expo
Flutter
Yes, Flutter web

Who to hire

Native (Kotlin / Swift)
Android and iOS developers
React Native + Expo
React/TypeScript developers with mobile experience
Flutter
Flutter/Dart developers
Facts are from the official documentation; hiring and team estimates are an engineering trade-off — check them against your market

Performance is deliberately not reduced to a single number in the table: all three approaches end up running compiled native engine code on the device, and bottlenecks usually lie in the specific app — long lists, heavy images, unnecessary re-renders. Compare a prototype of your heaviest screen on a real mid-range phone rather than generic benchmarks.

Builds and publishing: what every stack shares

However the app is written, the output is a package for Android and a package for iOS, signed with developer keys and reviewed by the stores. The differences between stacks are smaller here than they seem.

  1. Developer accounts

    Google Play Console and the Apple Developer Program are registered to the company that owns the product, not to the contractor.

  2. iOS builds

    The React Native documentation says it plainly: building projects with native code for iOS requires a Mac. Cloud services such as Expo’s EAS Build build the iOS version on their own macOS machines.

  3. Signing

    Android signing keys and iOS certificates are critical secrets: lose them once and the trouble lasts. EAS Build can store and issue them for you; with a native build the team is responsible.

  4. Store review

    App Store and Google Play requirements are the same for every stack: a framework does not get around them.

  5. Updates

    Users get new versions through the store. For JavaScript code, Expo offers updates without a rebuild (EAS Update) within the stores’ rules.

How to choose: a decision tree

Below is the order of questions we use as a starting point. It is not a rule but a way not to miss what matters: a “yes” to an early question usually outweighs all the later ones.

  1. Is the browser enough?

    If the scenario is a catalogue, booking or customer account and app stores are not required, start with a PWA or a responsive web app.

  2. Does the product depend on one platform or deep integration with it?

    iOS only, widgets, Apple Watch, CarPlay, complex camera or background Bluetooth work — native development removes the risk of waiting for wrappers.

  3. Do you already have a web product and a React/TypeScript team?

    React Native with Expo lets you reuse the language, approaches, types and part of the business logic, while Expo covers the typical native infrastructure.

  4. Do you need an identical branded UI on every platform, and is the team ready for Dart?

    Flutter gives full control over every pixel thanks to its own rendering.

  5. Do you have a strong Android team writing Kotlin?

    Consider Kotlin Multiplatform: shared logic, native UI on each platform.

  • The device APIs the product cannot work without are listed and their support in the chosen stack is checked
  • It is clear who will maintain the code in two years and how easy it is to find a replacement
  • You have decided whether you need the web from the same codebase
  • The heaviest screen has been prototyped on a real inexpensive phone
  • You have decided where and by whom the iOS version is built and where the signing keys are kept

Next on the path: your first app with React Native and Expo — from create-expo-app to a styled screen, then navigation with Expo Router. For Flutter there is a separate lesson on Dart and widgets.

Tell us about your task — we'll review your request and get back to you

Got a project?
We'll scope and estimate it — for free.

Tell us about the product or the problem. After reviewing the task we'll come back with an architecture, a timeline and a price for the first version.

  • Scope and risks estimated before we start
  • NDA — yours or ours
  • Work starts within a week

Please do not send passwords, access keys or source code through this form — we will agree a safe way to share access separately.

By clicking the button you agree to the processing of your personal data.