Every time you read about cross-platform frameworks on the internet, it seems like someone is trying to convince you of something. Flutter developers write about Flutter, React developers about React Native, and .NET developers about MAUI.

I’m in that last group, but I won’t be biased here. Based on my research, I want to help you answer two questions:

  • What problem are you actually trying to solve?
  • Which cross-platform framework will help you build something good without giving you a lot of trouble?

There will be no winners here. Just the trade-offs, with sources.

Bottom line: if your team writes C#, .NET MAUI is the lowest-friction fit. If your team writes JavaScript or TypeScript, React Native is. If pixel-identical UI and custom animation across platforms matter most, and your team is willing to learn Dart, Flutter deserves a serious look.

What each framework is

  • React Native: Meta open-sourced React Native in March 2015. You write JavaScript or TypeScript. The old asynchronous bridge is gone: the New Architecture (JSI and Fabric) became the default in 0.76, and 0.82 is the first release that runs entirely on the New Architecture. Massive ecosystem.
  • Flutter: Flutter 1.0, the first stable release, shipped in December 2018. You write Dart, and Flutter’s own engine draws every widget instead of using the platform’s controls.
  • .NET MAUI: the evolution of Xamarin.Forms, generally available since May 2022. You write C# and XAML, and a handler architecture maps cross-platform controls to native ones. The current supported release is .NET MAUI 10, which shipped with .NET 10 on November 11, 2025. If you want the rest of that release, I covered it in what’s new in .NET 10 and C# 14.

How each framework renders UI

This architectural difference is the most significant one between the three.

React Native and MAUI both end up with the platform’s own views on screen. In MAUI, handlers map each cross-platform control to a native view: a Button becomes a UIButton on iOS and a MaterialButton on Android. React Native does something similar for its core components. As the docs put it, “at runtime, React Native creates the corresponding Android and iOS views for those components”: <View> becomes a UIView or ViewGroup, <Text> a UITextView or TextView, and <TextInput> a UITextField or EditText.

Because the controls are native, you inherit much of the platform’s behavior:

  • accessibility
  • system animations
  • platform-specific gestures
  • OS-level dark mode support
  • text rendering

Flutter makes the opposite bet. It ignores native controls and draws everything with its own rendering engine. Every pixel in your app is painted by Flutter, not by the OS.

Which renderer Flutter uses depends on the platform, not just the Flutter version. According to the Impeller documentation:

  • On iOS, Impeller is the only renderer.
  • On Android, Impeller is the default on API 29+ devices with Vulkan; older devices fall back to OpenGL.
  • On desktop, Impeller has been the default since Flutter 3.47.
  • On the web, Flutter still uses Skia.

This has real consequences:

  1. Flutter apps look the same on every platform. The Flutter FAQ describes the goal as “consistent performance and appearance across platforms”. Because Flutter owns the whole rendering pipeline, custom animations don’t depend on what each OS’s controls can do.
  2. React Native and MAUI apps feel native, but platform-specific differences can show up: the same control can behave slightly differently on iOS and Android.

Neither approach is objectively better. They’re different bets about what your users value.

Performance: startup, rendering, debug builds and app size

All three frameworks can build fast apps. All three can build slow apps. In my opinion, how you build the app matters more than which framework you pick.

That said, there are differences worth knowing:

  1. Cold start time: I couldn’t find a neutral, current benchmark comparing the three, so measure on your own target devices. What each project documents: Flutter release builds are compiled ahead of time to native machine code. MAUI improved Android startup over Xamarin.Forms; Microsoft measured a Shell app going from 817.7 ms to 568.1 ms at MAUI’s GA release. React Native’s New Architecture removes the bridge, which the team says “improves startup time by avoiding bridge initialization”, and native modules are now loaded lazily.
  2. UI rendering: Impeller “compiles all shaders and reflection offline at build time”, which is aimed at predictable performance instead of shader compilation jank at runtime. React Native’s Fabric renderer is a real improvement over the old bridge-based setup. MAUI renders through native controls, so rendering behavior follows each platform’s own UI stack.
  3. Debug vs release: this matters especially for MAUI. Debug builds use the interpreter so hot reload works, and Microsoft warns this “significantly impacts performance and produces unrealistic results”. Their advice: always profile Release builds, because a slow debug build tells you little about production.
  4. App size: the Flutter engine adds “a small baseline footprint (a few megabytes compressed)”, and the final size is “largely determined by bundled assets, fonts, and third-party packages”. MAUI and React Native also ship a runtime with your app, so don’t assume any of the three is small by default. For MAUI, trimming reduces app size. Whatever you pick, measure release builds.

Which framework fits which team

Choose React Native if:

  • Your team is primarily JavaScript/TypeScript developers
  • You’re extending an existing React web application to mobile
  • You need the broadest possible library ecosystem
  • Your app is mobile-first; desktop is possible through Microsoft’s out-of-tree React Native for Windows and macOS, but it isn’t part of the core project

Choose Flutter if:

  • You want pixel-perfect UI consistency across all platforms
  • You need smooth, custom animations
  • Your team is willing to invest in learning Dart
  • Your app is primarily consumer-facing with heavy UI requirements
  • You need Linux desktop support

Choose .NET MAUI if:

  • Your team is already in the .NET ecosystem
  • You’re migrating from Xamarin.Forms
  • You need desktop alongside mobile, and Windows (WinUI 3) and macOS (Mac Catalyst) are enough; MAUI has no official Linux support
  • You want to reuse Blazor components in an app shell (Blazor Hybrid). Note that BlazorWebView renders Razor components into an embedded WebView, not into native controls
  • You’re building line-of-business or enterprise internal apps
  • You want a single CI/CD pipeline with familiar .NET tooling

The honest scorecard

✅ means strong support, ⚠️ means possible with caveats, ❌ means not supported. Platform and integration rows follow the sources above; the custom animations, ecosystem, tooling, learning curve and maturity rows are my own assessment.

DimensionReact NativeFlutter.NET MAUI
Native look & feel✅ platform views⚠️ custom rendering✅ native controls
Custom animations⚠️✅⚠️
Desktop support⚠️ via Microsoft out-of-tree✅ Windows, macOS, Linux✅ Windows, macOS
Ecosystem size✅✅✅⚠️
.NET integration❌❌✅✅
Tooling maturity✅✅✅✅
Learning curve (.NET team)HighHighLow
Learning curve (JS team)LowHighHigh
Production maturity✅✅✅✅✅
Blazor integration❌❌✅✅ via WebView

Summary: pick the framework that fits your team

If your team’s bread and butter is C# code, MAUI is the lowest-friction fit for mobile and desktop. No framework is objectively the best. The reason is fit: MAUI matches your existing skills, tools, and ecosystem.

If your team speaks JavaScript, your adoption cost for React Native is much lower, and its ecosystem is enormous.

If you’re building a consumer app where UI polish and animation quality are the key differentiators, you should seriously evaluate Flutter’s custom rendering.

The wrong move is picking a framework your team can’t be productive in, or one that doesn’t fit the platforms you need to ship to.

The right decision is the one that matches your team’s real profile.