Flutter vs React Native: Where Is Cross-Platform App Development Headed?

ProfilePicture of Will Eizlini
Will Eizlini
Two characters organizing mobile app components on mobile phone

If you work in mobile app development, and especially cross-platform app development, you’ve probably heard of Flutter. Like its sister, React Native, Flutter is an open-source framework and ecosystem best known for creating cross-platform iOS/Android applications, though it is also expanding to web and desktop applications.

Flutter was created by Google in 2018 and has steadily grown in popularity over the last four years. According to this survey, it’s actually now surpassing React Native in its use as a cross-platform development framework. Developers are excited about Flutter because it seems to address key pain points they encounter with React Native, particularly around performance, interoperability, and tedious testing requirements. 

That isn’t to say that Flutter doesn’t have its drawbacks, however. For one, Flutter is still a fairly young technology, which may explain why React Native remains the framework of choice for many big-name apps such as Facebook, Instagram, Uber Eats, and Airbnb. 

So, if you’re debating whether to opt for Flutter or React Native for your next project, there are a few key questions you will want to ask:

  1. Is Flutter mature and stable enough for my project?
  2. Is it truly a better framework for cross-platform app development? 
  3. What kind of projects is Flutter best suited for? 
  4. Is it likely Flutter will continue to grow, or will it fall out of favor like so many technologies in the past? 

To help answer these questions, let’s start with a deep dive into the Flutter framework, its current performance, and its niche in cross-platform mobile development in 2022. We’ll take a look at the solutions it offers to problems commonly faced by mobile developers, as well as its limitations. Finally, we’ll put it all together to answer the question, “Is Flutter the future of cross-platform app development?”

What Is the Flutter Framework?

Flutter is defined on the flutter.dev website as “an open source framework by Google for building beautiful, natively compiled, multi-platform applications from a single codebase.

It uses Dart, a fully object-oriented, strictly typed, null-safe programming language that compiles to native Arm64 and x86 code. Flutter code is composed of basic structures called Widgets, which are inspired by React components and work in a similar fashion. In React, the Component class has a Render method that returns a tree of JSX components. Similarly, Flutter Widgets have a build method that returns a tree of Widgets.

In the “hello world” example below, you can see how similar Flutter code is to React Native. Both platforms are reactive; like React, Flutter will update only the parts of the UI that have changed. 

FLUTTERREACT
import 'package:flutter/material.dart';


class HelloWorldApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text(
        'Hello, world!',
        textDirection: TextDirection.ltr,
      ),
    ),
  );
}
import React from 'react';
import { Text, View } from 'react-native';

class HelloWorldApp extends React.Component {

 render() {
  return (
    <View
      style={{
        textAlign:"center"
      }}>
      <Text>Hello, world!</Text>
    </View>
  )
}

Dart’s declarative constructors resemble the props that React uses in many ways, but without the JSX html-like markup. Instead, you see a series of nested widget constructors with their named constructor properties.

But the similarities end there. As we’ll explore in the next section, Flutter renders the UI in a fundamentally different way than React Native, and this is what has a lot of developers excited.

The Benefits of Flutter Over React Native for Cross-Platform Development

In many ways, Flutter was designed to address fundamental pain points that emerged when programmers began developing cross-platform code in React Native. 

When built, React Native, translates components like View and Text into native iOS and Android equivalents. Since these native components are fundamentally different from each other, the resulting look and feel can have significant differences between Android and iOS. Addressing these differences can be time consuming, often requiring developers to spend more time testing and debugging the look, feel, and behavior of UI components. This is one of the primary problems that Flutter helps developers address. Below, I explore some of the main improvements of Flutter over React Native for cross-platform development in depth. 

Flutter Renders Consistent, Pixel-Perfect UIs 

When compared to React Native, Flutter takes a completely different approach to rendering the UI. It draws the UI directly using Skia, the same graphics library used to render websites in Chrome. Skia is written in C/C++ and makes extensive use of the device’s GPU, which makes it blazingly fast. Coupled with Flutter’s smart updates of only widgets that have changed, this approach makes the UI respond almost as fast as it does in native apps.

Graphic depicting how UI components are rendered directly in Flutter using Skia graphics library
Image Source

Since the iOS and Android versions of Flutter have the same rendering engine, the resulting UI is predictable and “pixel perfect” across various mobile device types and operating systems. Clearly, Flutter can save a lot of time that a developer might otherwise spend testing on different devices.

It Frees up UI/UX Designers to Experiment and Innovate 

The consistency of UI rendering across platforms can free designers to think outside the box. Because they don’t have to worry about extensive debugging on different platforms and inconsistencies in rendering and behavior, Flutter app designers have more freedom to design and implement innovative UIs without being constrained by the limitations of native components. While this can be incredibly freeing, it also has its drawbacks (which I’ll explore later in this article). 

Flutter Truly Compiles to Faster Native Code

There’s a misconception that React Native compiles everything to native iOS and Android. While it does convert the components into native equivalents in each platform, for the most part, they are controlled by code interpreted by a JavaScript runtime. This adds an additional layer in the app at runtime. Because of this, the app may be slower (and larger) than a truly native app, because it has to include a runtime JavaScript interpreter. 

While Flutter apps are larger when compared with truly native apps, it’s comparable in speed. That’s because Flutter compiles the controlling code directly into arm64 and x86 native code. This increases the speed and responsiveness of the app and usually results in a smoother experience (depending on what it does). If the app simply draws native components and doesn’t do much in terms of calculations, for instance, the differences in speed from an app built on React Native may be trivial. In fact, under certain circumstances, React Native may be faster. But if the app performs a lot of calculations, Flutter will be significantly faster.

Third-Party React Native Packages Can Break

Since the basic components in React Native are few and simple, more complex UI components are often implemented in third-party packages. Occasionally, updates to iOS or Android can cause these packages to break. While this happens infrequently in practice, it consumes a lot of time for the team when it does, as developers are forced to find workarounds until the third-party package is updated.

With Flutter, these problems simply don’t happen, because the rendering engine remains constant when the phone’s OS updates.

Flutter Apps May Require Up to 50% Less Testing Than React Native

With Flutter, the rendering engine is consistent and there is a single code base in Dart for the controller code. Any bugs in the UI are likely to occur in both Android and iOS, so there’s less of a need to extensively test the UI on both Android and iOS devices.

Typically, working with different device sizes and layouts can require a lot of testing. With Flutter, however, this is often not the case. That’s because the rendering engine is reliably identical on both iOS and Android, so testers don’t have to worry as much that the behavior and rendering of the UI will vary. 

Flutter’s Popularity and Ecosystem Are Growing Fast

Because Flutter is a relatively new framework, the Flutter ecosystem is younger and less established when compared to the open-source packages available for React Native. However, my general feeling as a developer is that the Flutter ecosystem is healthy and growing nicely. As you can see, the number of questions on Stack Overflow is climbing, suggesting a growing community interest: 

Graph comparing number of questions for Flutter vs React Native on Stack Overflow
Image Source

What’s more, the Flutter repository on GitHub has 138,000 stars (React Native has 102,000). While there is debate on what GitHub stars actually mean for developers in practice, this does provide evidence that Flutter is a popular and widely talked-about framework. Similarly, on GitHub, a search for “Flutter” yielded over 380K results, while “React Native” yielded 286K results at the time of this writing (May 2022). It should be noted, however, that many of the first few pages of Flutter results are dedicated to demos, samples, and tutorials, while the results for React Native are made up of more usable packages. 

Table comparing Flutter vs React Native Github Metrics, including stars, search results, and available packages

That said, the number of packages available for Flutter is growing. A 2020 article found that, in 2019, there were approximately 2,000 packages; by mid-2021, that number had risen to 18,000.

Doing a quick search today, I see over 29,000 packages. For comparison, a search for “React Native” on the NPM website returns nearly 38,000 packages.

So while there may be fewer packages currently available for Flutter development, it’s clear that in the last three years a great deal of open-source contributors have been hard at work developing for Flutter, and that’s a promising sign!

Flutter Support for Web, Desktop, and More

Since version 1.5, the Flutter team has expanded the framework to target web and desktop apps for Linux, Windows, and MacOS. This is an exciting development for programmers. While React Native has a port for web, there’s no official support for developing desktop apps with it. A few experimental forks have been developed, but they weren’t built by the main React Native team. Because of this, the majority of them had been abandoned or deprecated by mid-2021, and are no longer being maintained.  

Given that Flutter’s rendering engine is consistent across whichever platform it can be ported over to, and the fact that it compiles to native code, Flutter seems much better-suited for developing desktop apps than any of those React Native forks, and therefore, can potentially achieve some success in that endeavor. 

Samsung Porting Its Tizen Based Devices to Flutter

In 2021, Samsung began working on an open-source port of Flutter for Tizen. Tizen is a platform that is used in Samsung’s Galaxy watches and also is used in apps for its Smart TVs. 

This is another good sign, hinting that Flutter may find its place in a greater variety of devices in the future.

Limitations of Flutter: Considerations for Cross-Platform Development 

Flutter is not a development platform that is best for all projects. Like any framework, it has its strengths and weaknesses and certainly is better suited to certain types of apps over others. 

Innovative UIs Can Be a Double-Edged Sword

A strong argument many developers have against hybrid apps is that users expect apps to behave in a certain way. It’s no secret that the user experience in iOS is radically different from that of Android. Because of this, trying to bridge that gap with a solution that’s not optimized for either platform can leave both groups feeling alienated. As such, user experience should be carefully considered and mapped out in order to minimize that risk. 

Flutter Cannot Natively Access Hardware

Developers may run into issues with Flutter if they’re designing an app that makes extensive use of hardware on the phone, such as cameras, microphones and sensors. While there are a lot of packages that can help bridge that gap, Flutter doesn’t support them out of the box. Consequently, if you are extensively and consistently connecting with the hardware of your phone, Flutter may not be the best choice.

Dart Is a Less Common Language, so Hiring May Be Harder 

One of the great selling points for React Native is that knowledge of JavaScript is common among programmers. In fact, most code bootcamps focus primarily or solely on JavaScript development. Dart, on the other hand, is not a commonly known language, so it’s not as easy to find a Dart developer as it is to find a JavaScript developer. 

That said, while Dart has its own idiosyncrasies that may take some getting used to, it also shares many similarities with other strictly typed languages: the code block, its control structures and general syntax resemble a kind of JavaScript/Java/Swift hybrid. Programmers coming from strictly typed languages may find the transition fairly painless, while those who have spent a lot of time working with React Native may find a fairly steep learning curve adapting to Dart syntax. So, while it may be harder to find a mobile app developer with extensive experience in Dart, training developers who are newer to the language isn’t unrealistic.  

UI Declarations Aren’t as Readable as React Native

Now, I admit this may be a personal bias, but I find the nested tree structure in React’s JSX is far more readable than Flutter’s declarations of Widget trees. I think this to be particularly true if a widget is building a rather large tree.

Complex Flutter widget trees are arguably hard to read. They look like some kind of lisp UI:  functions within functions within functions, with constructors declaring named properties instead of quoted properties inside an XML-like tag. Embedded child components are declared in the widget constructors as a property called “child” or “children.” In my opinion, this is far more verbose and lacks the elegance that JSX has, simply because JSX tags are nested within each other.

Default State Management Is Tedious and Verbose

Out of the box, Flutter has two core UI base classes: StatelessWidget and StatefulWidget. Creating and implementing a widget that has a state is far more verbose and requires more boilerplate code in Flutter when compared to React Native.

Because React Native uses functional widgets and hooks, state management is simple and easy to read. Custom hooks are easy to re-use and can be easily adapted to inject into a component states from various third-party state management libraries (such as Redux or Mobx). In contrast, default Flutter Stateful widgets require the implementation of a custom state class. In some cases, such as creating animations, you can end up with a variety of widgets that share similar functionality, yet still require you to write similar code over and over again. As a programmer, I dislike that. 

It should be noted that there are a number of third-party solutions the community has developed that can help address this. For example, there is a package that emulates the functionality of React hooks, and in particular, makes animations simpler. There are also packages that port over popular state management libraries for use with Flutter widgets.

In iOS development, the equivalent of Flutter would be SwiftUI (without being cross-platform), and their way of managing state is simply to define a property with the decorator @State. Flutter should do this since Dart supports decorators. 

I think it’s reasonable to assume that while Flutter’s approach to state management is presently a limitation, it may not always be so. Programming languages and frameworks tend to become less verbose as they evolve. Five years ago, React/React Native was far more verbose than it has become now. We may expect that future versions of Flutter will follow steps and become more streamlined as well.

Targeting Mobile, Web and Desktop in Practice Doesn’t Happen

As a seasoned developer and a bit of a realist, personally, I think it’s unlikely that a single project will target mobile, web and desktop from a single code base. Primarily, that’s because desktop and web apps use a fundamentally different UI language than phones and tablets do. 

For example: on mobile phone apps, we’re accustomed to seeing a navigation bar at the bottom of the screen close to where our fingers are in relation to holding a phone. But on a website or desktop apps, navigation occurs on top.

The main advantage of using Flutter for desktop platforms is that Dart would be compiled to the native processor on the machines. This speed opens up possibilities that using a JavaScript interpreter does not. That in itself bodes well for the future of Flutter as a cross-platform framework for desktop apps.

So, Is Flutter the Future of Cross-Platform App Development?

Flutter, overall, seems to be an excellent solution for developing a single codebase that reliably creates the same experience in Android and iOS. It addresses many of the difficulties that arose from teams developing in React Native. Flutter is fundamentally faster (especially in apps that are heavy on computations), the UI is far more consistent between platforms, and it has the power to expand into desktop apps, and even being supported in watches and smart TVs.

Flutter has some drawbacks, to be sure. Dart is still relatively obscure when compared to JavaScript, and Flutter has a  rather ornery declarative syntax and verbose state management code. However, I think we can expect those to be resolved as the framework matures and gains popularity. 

Overall, Flutter seems like a great alternative to React Native and one that can take over hybrid app development. The bigger question that remains to be answered is whether hybrid apps are the way forward; if they are, Flutter will surely be there.


Looking to hire?

Join our newsletter

Join thousands of subscribers already getting our original articles about software design and development. You will not receive any spam. just great content once a month.

 

Read Next

Browse Our Blog