App development

Flutter or React Native

The main difference between the two is one thing: Flutter draws the interface itself, while React Native invokes the actual Android and iOS views. Every other difference you hear about, from the language and the ecosystem to how the app feels, follows from that single architectural choice.

  • Lesson 4 of 8
  • Intermediate
  • Free, no signup

Two pans, no winner

Neither pan is heavier. What tips it is your project.

The Flutter pan

  • It draws the interface itself, so it is identical on both platforms
  • A bespoke design with a lot of motion is easier to build
  • Dart, with stateful hot reload and ahead of time compilation
  • A change in the OS look does not reach the app by itself

The React Native pan

  • It creates the platform own views, so it looks native
  • JavaScript and React, the thing a web team already knows
  • It follows along when the OS look changes
  • It does not give you hair for hair parity across platforms for free

This split is for business apps. For a game or a graphically heavy interface, neither of these is the default answer.

Last checked: Facts and tool names in this lesson are re-checked against their sources on this date.

Where does the real difference between the two sit?

In one sentence from each project own documentation. The official Flutter FAQ asks whether Flutter uses the operating system built-in platform widgets, and starts its own answer with one word: no. Flutter provides its own set of widgets, including Material and Cupertino, managed and rendered by its own framework and engine. On the other side, the React Native documentation says that at runtime React Native creates the corresponding Android and iOS views for your components, and that because the components are backed by the same views as Android and iOS, the app looks, feels and performs like any other app.

So: two different routes to the same picture. Flutter behaves like a game engine, taking its own canvas and painting everything onto it. The Flutter docs make that comparison themselves when they explain that Dart code on iOS is compiled ahead of time into a native ARM library that sits inside a runner project. React Native instead behaves like a driver: it paints nothing itself and tells the platform views what to do.

That difference has two practical consequences worth using in a decision. First, when the operating system changes how its components look, a React Native app changes with it and a Flutter app stays as it was until you update it yourself. Second, if your interface has to look exactly identical on Android and iOS, Flutter gives you that for free and React Native does not.

Which one is better? Neither. They are the answers to two different questions, and the rest of this lesson is about which question is yours.

Two glass brushes, one painting red and green strokes directly, the other pulling blue strings tied to blocks

The six axes that genuinely differ

RenderingLanguage
Following the OSSix axesthe things that genuinely differ between the twoDev cycle
Team and hiringNative access

None of these six decides on its own. The decision comes out of combining them with your project.

Dart or JavaScript: which is cheaper for your team?

Flutter is written in Dart. Dart own site describes it as a client optimized language for developing fast apps on any platform, and says Dart also forms the foundation of Flutter. The Flutter FAQ explains why Dart was chosen: the combination of two things, a JIT based fast development cycle that makes stateful hot reload possible, and an ahead of time compiler that emits efficient ARM code.

React Native is written in JavaScript with React. Its own documentation says you use JavaScript both to access the platform APIs and to describe the appearance and behaviour of your UI using React components.

Now the practical question: which is cheaper for you? The answer is almost always the one your team already knows. If you have web developers writing React, React Native works from about day one and a large part of the habits and tooling carries over. If your team has no web background and is starting from zero, Dart is a small language and learning it is no harder than JavaScript; in that case this axis is not the decision.

One thing we hear often in hiring interviews and it is not true: that Dart is a rare language and you cannot find people. What is genuinely rare is an experienced mobile developer, in either ecosystem. Someone who knows React does not necessarily know React Native; the release cycle, debugging on a device, signing and the platform APIs are things you do not learn on the web.

How do you judge the ecosystem without leaning on an unsourced number?

Comparison articles usually reach for market share numbers here. We will not, because those numbers have no citable source and in any case have nothing to do with your decision. The right question is not which ecosystem is larger; it is whether the three or four capabilities your app cannot work without have live support in one of them.

So write your own list. Payment gateway, maps, notifications, camera, barcode scanning, sign in with an account, whatever it is. Then search for each one in the package registry of that ecosystem: pub.dev for Dart and Flutter, and npm for JavaScript.

And look at three things in each package that counting stars will not find. One, the date of the last release; a package with nothing published for a year becomes your problem on the next OS version. Two, whether the package wraps a native SDK or reimplements it; one that wraps the official SDK usually keeps up when that SDK updates. Three, whether the open issues are about the platform you actually care about.

A point that is the same in both ecosystems and gets forgotten in the decision: every capability wired to hardware or to a platform service eventually needs someone to write its native code. If a good package exists, that someone is not you. If it does not, it is you, and it has to be in the project estimate. Our own app development page says the same thing: before proposing any route, we first ask what the app is meant to do.

How to judge a package before you lean on it

Package assessment sheetbefore you commit

Look at these

  • The date of the last release and whether it was tested on the latest OS
  • Whether it wraps the official SDK or reimplements it
  • Open issues on the platform you actually care about
  • The licence and whether it fits your commercial use

Do not use these as the measure

  • Market share figures in comparison articles
  • Star count without looking at the date of the last commit
  • That a large company mentioned its name somewhere

This sheet works the same in both ecosystems. Star count is on neither side, because it says nothing about maintenance.

So which one should I pick?

Three questions, in this order. First, what does your team know today? If they write React, React Native is the default pick and you need a reason to move away from it. Second, how bespoke is the interface? If your design is full of motion and non standard shapes and has to be identical on both platforms down to the hair, Flutter is what was built for that. Third, how many native SDKs have to be wired in? The larger that number, the more weight goes to whichever ecosystem has a living package, and that has to be judged for your project rather than in general.

And our position, which is rarely written on a sales page: for the app of a mid sized Iranian business, a content list plus forms plus payment plus notifications, both frameworks do the job and choosing between them is not the bottleneck of the project. The bottleneck is usually elsewhere: the backend, the interface design, and who maintains it after delivery. If a contractor turns the framework choice into the most important decision in the project, they are probably avoiding the real subject.

There is one genuine exception. If your app is a game or has a graphically heavy interface, neither of these is the default answer and you should go to the tooling of that field. And if the app is only a mobile version of your site, you may not need an app at all; ask that question before choosing a framework, not after.

The decision starts from what you have, not from what is better

What does your team write today?

If they write React and web

React Native

  • The language, the libraries and the habits carry over
  • The interface stays in step with the platform look
  • Moving away from this branch needs a reason
If the interface has to be identical hair for hair

Flutter

  • Parity across the two platforms comes for free
  • A bespoke design with a lot of motion comes out cheaper
  • In exchange, keeping the look up to date is on you

This tree works when the app is a business app. For a game neither branch is the answer.

The fast path, with AI

You can read framework comparisons for hours and get nowhere. The faster route is to turn the question around: instead of asking which framework is better, split your own feature list in two, the features the framework handles by itself and the features that reach for a platform capability. It is the second group that produces the real cost. This work needs judgement and breadth, so put a strong model on it rather than a cheap one; our current pick is in the AI section of this site.

  1. Write the feature list in plain language, one sentence each. Like: the user signs in with a mobile number, places an order, pays, and gets the order status by notification.
  2. Run the recipe below. The output is a table, not a recommendation.
  3. Search every platform capability the table names in that platform official documentation. If a name the model gave is not in the docs, stop there: the model invented it.
  4. Now, and only now, search pub.dev and npm for those few capabilities and run the assessment sheet from earlier on this page against each package. The framework decision comes out of that table, not out of an article.

Copy-ready recipe

This is the feature list of a mobile app that will be released on Android and iOS.

For each feature give one table row, with these four columns and no extra commentary:
1) The feature itself, in the sentence I wrote.
2) "Interface" or "platform capability". If it is only screens, forms, lists and navigation, interface. If it reaches for hardware or an operating system service, platform capability.
3) For platform capability rows only: the name of that capability at the operating system level, separately for Android and for iOS. Write the name of the platform own official API or framework.
4) One short risk: the thing that usually breaks in practice in that capability.

Strict rules:
- Write no third party package or library name. Write no version number.
- Do not recommend which framework is better. Give the table and stop.
- If you are not sure about a row, write "unsure" in the third column and do not guess.

Features:
{feature list}

Before you trust the output: The third column is exactly where a model may invent a name, and an invented name looks precisely like a real one. Search every name it gives in the official Android and Apple documentation; if it is not there, throw that row away. And take no framework decision out of this table until you have looked at the real packages on pub.dev and npm yourself. The table is a list of what to check, not the result of the check.

AI in this kind of work

In choosing a framework, AI is useful for one job and dangerous for another. Useful: breaking requirements down into platform capabilities, the job described in the fast path above, because it needs breadth and is easy to verify. Dangerous: asking which framework is better or which package to install, because the model answer sounds confident in both cases and is harder to check.

Tools that actually help

  • Claude Good at breaking requirements down into platform capabilities and at reading a package source before you lean on it. Iran is on neither of Anthropic two supported-countries lists; we read that on Anthropic own page.
  • Gemini Cost effective for bulkier passes over code and for summarising documentation. Google own page says the Gemini web app runs in over 230 countries and territories, and Iran is not on that list.
  • Claude Code Once you reach the code stage, a command line tool works on the real repository rather than on pasted text. Claude Code runs on the same Anthropic account, and Iran is not on the supported-countries list.

Where it backfires

There is one specific risk here and it has a package name. When you ask a model which package to install for a given job, the answer is usually a name that looks plausible, and if that name does not exist you have searched a package registry for an empty name. It becomes serious when somebody registers that name. That is exactly why the recipe above forbids the model from giving package names: you take the platform capability name and find the package yourself on pub.dev and npm.
The second risk is softer and we see it often in consulting calls: a model answers positively about both frameworks, because both are praised in its data. Ask whether Flutter is good for your project and you get yes; ask the same about React Native and you get yes. Our position: do not ask the model to choose, ask it to list what you have to check. For how each tool can be paid for from Iran, see the buying guide.

Sources: Flutter FAQ: does Flutter use the built-in platform widgets React Native docs: Core Components and Native Components Anthropic: supported countries Google: where Gemini Apps are available

Where this advice stops

This comparison is only about mobile apps. Both frameworks have other targets, from desktop to web, and the equation differs there and we have no first hand experience of it to write here. Second, we gave no performance numbers for the two and that is deliberate: a performance figure means nothing without saying on which device, with what interface and in what version it was measured, and the numbers circulating in articles do not say. Third, if the team building the app has real experience in one of the two, that axis outweighs every architectural argument on this page.

From our own work

We have made this same architectural choice on the web and paid its bill. None of the figures on this site, from diagrams to charts, are drawn with an off the shelf library: the rgb.ir theme has its own shape library of 52 archetypes, each one an rgb_dg_* function in the inc/diagram*.php files. The measure is simple and you can count it yourself: in assets/css/diagram.css the number of url( occurrences is zero, which means no image is ever loaded, and no JavaScript file in the assets/js folder touches these shapes at all.
The benefit of that choice is Flutter benefit: the output is identical on every screen and no third party library goes missing halfway. The cost is Flutter cost too, and we paid it this year: when the Learn section of this site needed shapes we did not have, nobody built them for us. The file inc/diagram-lib2.php holds fifteen new archetypes that we wrote ourselves. An off the shelf library would have given those fifteen for free and decided how they look in exchange. That is exactly the trade this lesson is about.

Real follow-up questions

Which of the two is faster?

It has no answer in that form, and when someone gives you a number, ask on what device and with what interface it was measured. For an ordinary business app both are faster than the point where a user notices, and the slowness usually comes from the network and the backend rather than from the framework.

Can you get a web and desktop version out of these two as well?

Both have targets beyond mobile and their own documentation says so. But a practical point: producing a build with one command does not mean that version is ready. An interface designed for a thumb looks odd on a desktop and the other way round, so that version needs design work of its own.

If we regret it later, how hard is the migration?

The interface layer is effectively rewritten, because none of the interface code of one is usable in the other. What survives is the backend, the API and the business logic, if you kept them separate from the start. That one sentence is a good reason to write the logic apart from the interface, whichever framework you pick.