flutter vs react native

Flutter vs React Native – cross-platform frameworks comparison

Cross-platform app development is making a lot of noise these days. As software houses along with their clients are scrambling to keep up, we take an in-depth, technical, look at the 2019 top-rated cross-platform frameworks. I’m hoping to give you a bit more than just a general look or advice on what to choose. 

Table of contents

  1. React Native – the story so far
  2. The short story of Flutter
  3. How does React Native work?
  4. Building UI -React Native
  5. The data flow
  6. How does Flutter work
  7. Everything is a Widget
  8. Building UI – Flutter
  9. The architecture
  10. Familiar solutions
  11. React Native
    Hot / Live reload
    React Native CLI
  12. Testing – React Native
  13. Building app releases
    OEM Debugger (Original Equipment Manufacturer)
  14. Testing – Flutter
  15. Flutter – Learning curve
  16. Supporting newcomers
  17. Summary
  18. Easy building
  19. Community support
  20. Not reinventing the wheel

React Native – the story so far

React Native was created by Facebook. The story began at an internal hackathon project in the summer of 2013. Full public release of React Native took place at the 2015 edition of React.js Con. In March 2015, at F8, Facebook announced that React Native was now available on GitHub. Facebook, while developing its own products, such as Messenger, and utilizing their experience in the React.js web framework, created a solution for producing native application components from the JavaScript thread.

For a more general view of the framework, read about Pros and cons of React Native.

The framework’s quick rise to fame created quite a few misconceptions as to its capabilities and use. You can read more about it in our article “7 React Native myths vs reality”

The short story of Flutter

The first version of Flutter, code-named “Sky”, was presented in 2015 at the Dart developer conference. The first stable version, allowing to compile native Android and iOS applications from one code Version 1.0 was released at the Flutter Live event, December 2018. Among the top advantages of the framework, the creators mentioned smooth operation level with native applications, and maintaining the state of the Hot Reload application. The initial reception of the new framework were very positive, and first flutter reviews gave us a lot to look forward to. 

How does React Native work?

JavaScript is the primary programming language for React Native. The JSX extension is included by default to facilitate writing declarative UI components, just like in React.js. The programmer is not restricted in using other transpilers. That is why Flow, TypeScript or ReasonML are often found in React Native programming. In addition, you can use the latest language constructs like async / await or generators. Ultimately, after transpiling, the application on your phone is all JavaScript.

Building UI

React Native contains a set of standard UI elements, equipped with bindings to native components, to be used in the application according to the operating system. The components can be freely grouped in the hierarchical structure of the declarative view. They can render other declarative components, or components with native bindings.

Component (React.Component) is a fundamental concept in React Native. It is an object (or function) that has “props” and “state”. For given props and state, the component should return a view, but only when props or state change. Props are a type of arguments for a component that are set from the outside – the component has no control over them. State, on the other hand, is internal, private data, entirely and exclusively under the control of the component.

The data flow

React Native uses unidirectional data flow, which distinguishes it from other declarative frameworks such as Angular (two-way data binding). This results in better performance and easier debugging. The one-way data flow in React Native is done by giving the component in the rendering phase read-only props and state. It can freely transform them, pass them down the view hierarchy, but shouldn’t be able to mutate them directly. The same goes for child components that will receive this data as props. Modifying props or state directly will not refresh the view. To do this, use the component’s setState method (or a similar function when using Redux or other solutions). Event handling by child components should be accomplished by passing in callbacks’ props to handle events that ultimately implement the parent’s setState as needed.

How does Flutter work

Flutter applications are written in Dart, an object-oriented language with a type system that combines static typing with runtime control. It allows type inference so you can skip their declarations. It has async / await mechanism, which together with the Future type allows you to write asynchronous code as if it were synchronous. If you’re familiar with Kotlin or JavaScript, learning Dart shouldn’t be an issue.

Everything is a Widget

The basic building block of the user interface is the Widget. The operating principle is similar to React Native – Flutter’s documentation actually mentions React as inspiration. Individual elements are arranged in a hierarchical structure, rebuilt each time the state of the application changes. This does not mean, however, that the view is being built again and again. The returned structure is only an intermediary on which the framework modifies the visible interface. In this way, Flutter replaces the imperative style known from native platforms with a declarative style, taking  the burden of writing and managing transitions between possible interface states off the programmer’s shoulders.

Building UI

Flutter provides a wide range of ready-made widgets that comply with Material Design guidelines. The programmer has, among others, buttons, text boxes with titles, or wrappers that manage the position of beams or floating buttons. Arranging items on the screen may cause some confusion as we define the position and looks of components by placing them in containers. This often causes the structure to grow and forces you to remember the behaviors and relationships between several types of containers.

The architecture

The BLoC (Bussiness Logic Component) architecture is one of the solutions proposed by Google. It places use cases in separate classes. Communication with them takes place via asynchronous streams, where the interface publishes events in the appropriate BLoC “inputs” and at the same time, listens to the outputs for the flow of subsequent application states. The intermediary between these components and the interface is the StreamBuilder widget, which receives data from streams. The basic assumption of this architecture is to adapt the application to operate in an asynchronous environment – where a variety of data flows in at any time and in any order. 

Familiar solutions 

Native programmers familiar with RxJava and MVVM architecture will definitely find this to be a comfortable solution. However, this is not the only way, as Flutter can work with e.g. Redux and then state can be propagated by the components themselves. This process can be simplified by InheritedWidget which will shorten the path to the target component to which the data must travel. Provider can also be used as a solution, being a library combining Dependency injection and application state management. With its help, the programmer can provide the necessary values ​​to the appropriate locations in the interface. You can inject any objects, simple data, streams, or objects observing data changes (eg ChangeNotifier).

All of the above solutions are well documented and explained in official guides. This will help many programmers to implement solutions they already know.

Now let’s compare some of the main tools available to programmers working in cross platform frameworks.

React Native

Hot / Live reload

Hot reload provides strong acceleration of the development process, because every change in JavaScript can be seen on the phone almost immediately. The function is limited to debug mode only (metro bundler must be connected) and native changes are not visible.


All you have to do is install one Expo application on your phone, and you can download the RN application code from the internet or the QR code and instantly update it when it changes. It is not suitable for creating production applications, but rather for rapid prototyping. If we just want to add real push notifications, Crashlytics or any library not included in the Expo SDK, we must first complete the work with Expo and export (expo eject) the project to the “full” version.


We don’t even have to install Expo on the phone, as we can simulate the application in the browser!

React Native CLI

A program to generate a new React Native project. Unfortunately, very limited options, and the program is used from the terminal.

Usually there is a lot of initialization work left to be done e.g. generating certificates, adding dev / prod variants or hooking up Crashlytics. You can prepare a project template to initiate new projects faster, but React Native environment is changing so quickly that we would only use such a template once. Poor in comparison to project designers in Android Studio / XCode.


There are several frameworks for React Native. By default, “Jest” is enabled. We can easily add new unit tests by putting them to __tests__ and running the “npm test” command. You have to be careful when importing native modules – you need mocks, and these are often missing in npm packages, or work poorly.

Building app releases

Everything has to be done natively and we are limited to what Android Studio / XCode offers. We have 2 platforms to manage and there are no advantages of React Native hereFLUTTER

Flutter offers plugins to facilitate work in Android Studio and Visual Studio Code. They support project creation, debugging and the Hot Reload function.


A tool for debugging and profiling apps, from your browser. It allows, among others, to browse the interface in the form of a tree and to check individual widgets. It also allows you to track memory usage, CPU resources and app performance testing.

OEM Debugger (Original Equipment Manufacturer)

It allows you to debug not only Dart code, but also files generated for a specific platform. This is especially useful when writing your own system solutions.


Flutter offers its own plugin designed to perform unit and integration tests, and check widgets. For mock dependencies, the official documentation recommends Mockito.

Flutter supports flavors which allow you to configure various build variants, search among existing Android’s productFlavors and iOS’ schema. You can refer to them directly in the Dart code or call them out from Flutter CLI, but they must be configured separately for each platform first. The process has so far been described in Flutter community articles. What’s up with that, Google?

To prepare the release version, it is necessary to configure each platform individually. The documentation describes the process of editing individual files, but knowledge of Android and iOS will definitely speed up the process.

Flutter – Learning curve

Google actively encourages developers to learn and switch to Flutter. There’s plenty training materials available in form lectures and video tutorials.

The documentation is comprehensive, laden with examples, and thoroughly explains various aspects of working with the framework- from building an interface to writing tests. The authors of the framework gives us recipes for creating a variety of elements of modern applications. They also propose a straightforward and Flutter-friendly architectural model – the BLoC. The section dedicated to programmers familiar with other popular platforms, both mobile and web, is a huge help. It explains the key differences between Flutter and other programming environments.

Supporting newcomers

The support offered makes learning the framework easy. Depending on your experience, you may need to get up-to-speed with ReactiveX, declarative UI, or the async / await pattern. The framework uses the Dart language, not as popular as JavaScript or Java, so for some programmers it will mean having to spend some time learning the syntax. In the Stack Overflow popularity ranking from 2019, it took 22 place with a score of just 1.9% – the result far off the top spot holder – JavaScript. However, it is quite similar to other object-oriented languages ​​and has type security, so switching shouldn’t be all too complicated.

In addition, in the said ranking, under the category “Most Loved”, both languages ​​sport an almost identical result, JavaScript – 66.8%, Dart – 66.3%. The category reflects how many developers are interested in working with a given technology. Considering most results being close to 60%, Dart seems like an easy and interesting technology to learn.


Cross-platform frameworks keep developing and are gaining ground across IT landscape. Solutions that produce applications similar to native are definitely displacing hybrid solutions, offering better performance as well as native appearance and behavior of the application. Flutter and React Native seem to be top players important in cross-platform field.

The market shows a lot of interest in React Native apps. This comes not only from budget-conscious startups, but also from largest global brands. The framework seems the perfect choice for creating MVP versions of the software.

Easy building

Both frameworks build views in a declarative way. They introduce analogous concepts of Component and Widget, as basic building blocks of applications, operating on the basis of an unchanged state. Each of them also offers a Hot Reload function that allows you to quickly reload a working application and see introduced changes.

At the core, both technologies are quite similar. They use a declarative UI building style and are quite flexible, allowing the developer to apply various techniques to manage the state of the application. Access to device features is provided by plugins.

Community support

React Native in this field relies more on the community, having several separate libraries for handling the same tasks. This can be both a disadvantage and an advantage. Flutter remains under greater control of its authors, who continuously keep providing ready-made solutions. At the same time, they cooperate with a growing community for missing tools, such as database support.

The final decision on the use of technology belongs to the developers. Flutter as a junior framework is inevitably less popular. React Native, uses JavaScript and is based on React.js, so it can be more attractive to experienced web developers.

Not reinventing the wheel

That said, both technologies have certain levels of entry. Developers experienced in native app development will have to assimilate patterns known from web productions rather than what their used to, whereas front-end devs will have to face the specific patterns of developing for mobile platforms. Knowledge of particular platforms will also be useful, if only to improve the process of building and implementing applications.

Cross-platform vs Native development ebook - itcraft

Would you like to know more about differences between cross-platform and native app development? Download our ebook! It is the ultimate guide to Cross-Platform vs Native development. You will find out more about native applications, cross-platform applications and technologies used to build them.

See also

Top 4 technologies to develop your app in 2020
Flutter apps – starting work with the new Google cross-platform framework
Building mobile UIs – Flutter vs native Android SDK

5 (100%) 11 vote[s]