Flutter vs React Native: Everything You Need to Know

Flutter or React Native — which is best for you?

Image for post
Image for post

If you are considering developing a mobile app and your mind is set on going with either Flutter or React Native, but don’t know which one, this article will help you to make the decision! Both technologies are pretty well-known in the cross-platform universe. However, how can you determine which one is the right one for your business?

Throughout this article, we’ll guide you through an in-depth comparison of Flutter and React Native to help you choose which technology fits your idea better. We’ll explain their limitations and advantages so you can get the most out of each. It’s also worth clarifying that we won’t endorse one over the other as we discuss them from both a business and technical standpoint.

Why should you consider creating cross-platform apps instead of going ahead and writing your apps using Java/Kotlin or Swift/Objective-C? There are a lot of options to choose from when it comes to creating hybrid apps using the same codebase like Ionic, React Native or Flutter. Some of which use cutting-edge technology, offer good performance and are easy to get on board with.

A hybrid app allows you to have the same codebase for every app store. This is great because you can minimize development time and decrease costs. Also, fixed costs like an automated tool for continuous integration/deployment will be lower since your codebase stays the same.

With a hybrid app, adding features or functionalities is straightforward, just code and then deploy the tested changes directly to the stores, the same goes if you need to add fixes/patches.

Of course, as with any other technology, there are going to be some trade-offs. In the case of cross-platform technologies, in the past, people criticized their sub-par performance compared to that of native apps. But, with the development of cross-platform frameworks and the rise of React Native and Flutter, the difference has become almost negligible. This is especially true with Flutter, as we’ll see in a moment. There are tons of reports examining the performance of apps in Flutter vs Kotlin and Java or Swift that are very encouraging in terms of profiling speed and native functionalities. That said, now you can take advantage of having a single codebase with cutting-edge technology and full support and reliability in the dev community, but most importantly, great performance.

The question now is the other way around. Why should you consider writing your apps in native languages instead of using cross-platform frameworks? We can’t think of a sufficient reason, except if you have a large budget and want to go the “old school” route, which is perfectly fine!

Image for post
Image for post
Image for post
Image for post
Graphics source

What are Flutter and React Native?

It’s a library created by Facebook to create hybrid-native apps (Android, iOS) using a single codebase which was written on top of React. This is a great option if you already have a background in React Web. This library compiles to Android and iOS but doesn’t offer support for web or progressive web apps.

Image for post
Image for post

It’s a framework by Google that allows you to create cross-platform mobile apps and desktop apps with a single codebase. Learning Flutter requires having knowledge of Dart (its programming language). This library is optimized for mobile apps. It also allows you to create web and desktop apps, but this capability is still in beta.

Image for post
Image for post

Pros and cons: Flutter vs React Native

From a business perspective, it’s easier to start working with technologies that your developers already know.

React Native uses Javascript, a very popular and widely used programming language. So two things are likely to happen: Developers with a background in JS and ReactJS can easily move to React Native, and it won’t be too painful. Still, they would need to learn some new, mobile-related-stuff. But, in general terms, they should be ready to start shipping apps on RN.

On the other hand, Flutter uses Dart as a programming language. Dart is relatively new, since it was released in 2011 by Google. Although it’s gaining popularity, it’s difficult to find developers who have experience in it. Therefore, finding an experienced Dart/Flutter team could be a little bit more difficult. However, the internet is full of documentation and training on Flutter and the learning curve could be lower if the developer’s background is in any object-oriented programming language. It uses both of two worlds: Object-Oriented programming with the composition of highly-reusable components (a web development theory).

This makes it more difficult to take off with a Flutter team than with a React Native team. However, it’s worth noting the continuous growth of the Flutter community over the last few years. They have improved constantly in documentation, community support and the framework itself, which today is powerful.

Hint: Dart compiles to either native code or Javascript, that’s why it is possible to create mobile and web apps with Flutter .

As we all know, the faster you develop your product, the faster you’ll reach go-to-market. This is what you can expect from each technology:

RN has less boilerplate when it comes to creating components. Same as the web, just create a constant that returns a component and you’re done.

You can have stateful and stateless components just like ReactJS and the state-management could be anything used in web development like Redux. Creating an app in React Native is quite fast if your team already knows about React. If they don’t, it’s still quick because it’s just Javascript, a language that is easy to get on board with.

Flutter requires a bit more boilerplate when creating a component and other things such as state management. You may argue that having a good architecture and using design patterns can reduce it, but it’ll still require more than RN.

Given Flutter’s large library of components, creating an interface will be faster than in React Native. That’s because you won’t need to write as many things on your own. And, since Dart is an object-oriented programming language, for state management, you can apply many techniques to successfully handle state changes which will directly impact the amount of code, the boilerplate, and the complexity.

In a daily-to-day development project, you could end up having to code more with React Native because you need to write a lot of things on your own.

It is also important to think about what kind of application needs to be built. For example, Flutter is a powerful tool to work with animations. In general terms, it’s great to display any graphic content easily. Animations and graphic personalizations in RN are more difficult. For that reason, this kind of implementation will require more time.

The main building block of Flutter is a widget and for RN, a component. Widgets and components are interchangable, their main difference lies in the fact that Flutter widgets are already stylized to have either an Android or iOS look and feel by default, using Material or Cupertino library, respectively. RN core components, on the other hand, don’t have any styles out of the box, which means more work for your developers.

Now, you may be wondering why talking about components/widgets is important. The reason is simple: the more components/widgets you have available, the faster you can build features for your application.

Knowing that, let’s talk about each specific technology.

There is a huge number of libraries which expose components with already implemented functionalities for RN apps. However, if we talk about core components, the list is not as large as Flutter’s. This is because of the internal functionality of RN, where every core component is a reference to the native Android or iOS component itself. So, having a large list of base components is not feasible, since, unlike Dart, Javascript cannot compile to native languages.

However, if you think about it, there’s a good reason for having references to the native components: developers won’t have to build platform-specific views and that can positively impact development speed.

Flutter comes with large and well documented, ready-to-use widgets, most of which are implemented with material design concepts. This makes the process of creating beautiful interfaces easy and fast.

Unfortunately, Flutter widgets are not adaptive, for that reason, developers will have to make the platform-specific adaptation manually. The good thing is that, with Flutter’s widget approach, apps will look good on either old operating systems or up-to-date ones.

With that said and before making any conclusions, it’s worth noting the differences between core components/widgets and those from libraries. That way you can have a better understanding of what we are about to mention:

Core components/widgets are those which come by default. Meaning you can use them without any additional external dependency, which is good.

Components/widgets from libraries (custom components/widgets) are those which have been developed by people in the community to wrap up some common functionality in applications, for example, filters, type ahead inputs, internationalization, etc. The good thing about having a lot of custom components and widgets is that you can avoid creating your own implementation for complex functionalities, which will help save a lot of development time — thus money. There’s also a down side: when you use a third party component/widget in your application, you are also adding dependencies to it. Therefore, you will need to start worrying about any update, breaking change or issue resolution from any third party components/widget you use. This is time consuming and can significantly impact the proper functionality of an app.

Going back to RN and Flutter, the reason for mentioning all of the above is to point out that RN has a large list of libraries/modules that expose components, but its core component list is not that large. On the flip side, Flutter has a lot of core widgets but, there are not many libraries/modules with widgets we can use to avoid the implementation of certain functionalities on our own. Knowing the advantages and disadvantages of each, it’s up to you to choose what option suits you better according to your application requirements!

In either language, you can create a strong architecture, which is important for your product’s scalability and growth; you just need to know agnostic concepts or paradigms and apply those to the language you’re currently using.

It uses Javascript which is a very flexible language-it’s powerful — very different from the most common languages and you can use it however you want. You could write either an Object-Oriented architecture, a component-based one, micro frontends, a pure functional one, etc. Or even write everything in just one single file.

There is no “right” way of doing things. However, there are some proven architectures that can light up the way on how to architect and organize your app. Still, you will need to do some tweaks or adjustments to fulfil the needs of your software.

In the RN ecosystem, you can create your architecture however you choose with no restrictions. There are many styles and libraries out there that can handle component behavior, communication, utilities, global functionalities, languages, services, and routes in many ways. Since it is up to you how to mix them, it’s very easy to potentially apply the wrong concepts or mix unnecessary architectures, which could impact the development/performance of your app.

It uses Dart which is an Object-Oriented language, meaning that any classic architecture you want to apply can be done with confidence. There is a well-defined path for how to do it because the architecture options, per se, have constraints and restrictions, so you can ensure — not 100%, but to a good degree — that it will be correctly implemented.

When creating a widget or implementing an existing one, as well as the composition of components, there is a clear, singular way of doing it. So it’s likely you can not have a component with a hidden API or a component that does more than what it’s supposed to do. If you implement a widget in the wrong way, the compiler will raise an alert and won’t allow the app to initialize. But the component-based architecture is part of Flutter itself. Therefore, it’s not like you will need to add another architecture layer on top of it. Like any other visual library/framework, you can create stateful and stateless components to maintain your widget-system as simple and shareable as possible.

For state management, you have many options. In Flutter, you can adopt reactive architectures, machine states, linear data-flow and events, Dependency injection, PubSub, or just local state for a given container. The difference with RN essentially is that, since Dart is a highly typed language, making things like abstractions to reduce the complexity of an implementation or the boilerplate or ensuring that every module uses the same approach is more feasible to accomplish. Also, you could mix different approaches to come up with something more robust if the app requires it.

Smartphones have become one of the most used technologies for customers to interact with businesses — and the other way around — through applications.

Ensuring that customers have a positive experience accessing services, products or information they need directly translates to user engagement or retention. In the opposite scenario, slow, unresponsive apps generally lead to frustration, dissatisfaction and impact a company’s image, ratings and revenue. Here is when performance plays an important role in an application that supports a business.

The bottom line is it’s essential to offer a good user experience through high performance.

Now, from the mobile app perspective, we can talk about a metric called which is the number of frames an app is able to render in a second. This metric is directly related to app performance and shows how smoothly an app can run.

Built using a Graphics Library called Skia. This library does most of the work on GPU (graphic process unit) which allows the delivery of 60fps (frames per second) which makes Flutter apps perform seamlessly. Additionally, Dart, compiles directly to native code, controlling every pixel to avoid performance degradation or issues.

This is an important fact to have in mind in the building of any type of app, but even more so when that app includes complex design or animated graphics.

In this case, Javascript code transpiles to native code in execution time to have access to native modules of each mobile platform. This process of transpiling and then accessing components affects React Native’s performance. As a result, it doesn’t always achieve 60 fps (frames per second).

In the beginning, when Flutter was not yet in the picture, the discussion was all about moving to React Native and abandoning WebView-based tools like . This was just because using these tools, it’d be impossible to achieve 60fps as well as a native look and feel. But, with RN, that would be possible. The thing is that it doesn’t always happen:

“Where possible, we would like for React Native to do the right thing and help you to focus on your app instead of performance optimization, but there are areas where we’re not quite there yet.” ( RN official documentation)

A concrete example of how RN architecture affects performance is the following:

“For example, if you were to call this.setState on the root component of a complex application and it resulted in re-rendering computationally expensive component subtrees, it’s conceivable that this might take 200ms and result in 12 frames being dropped. Any animations controlled by JavaScript would appear to freeze during that time. If anything takes longer than 100ms, the user will feel it.” (RN official documentation)

So, the RN team still has work to do and specific issues to take care of that we hope they resolve soon.

In RN as well as Flutter, you can access the device and control things like phone vibrations, LEDs, cameras, contact lists, and settings, among other native functionalities. These layers of native access are in some cases better in one technology than the other and as everything, there are some caveats.

There are a lot of libraries in NPM from the dev community that you can install in your React Native project that allow you to access things like cameras, read QR codes, change the light in the front led, access and read SMS, and many other things. Since the community is large enough, you can find libraries for almost any native access you need. But there are some important limitations that are not supported yet or very hard to accomplish. For instance, if you need to have a background service running in the phone whenever your app is installed.

When you need to install a library to access native functionalities of the phone, you need to test on Android and iOS. That’s because there are many libraries that do not ensure the correct operation for all of the cases. So, you will never know if it will work until you implement it and test on every OS.

Regarding the look and feel with RN, you just need to create your components, style them and then those will inherit the style of every OS. Let’s say that you create a form with textboxes and buttons. The style of the textboxes and buttons will inherit the look and feel of iOS or Android automatically. No need to create work-arounds or extra styling layers in order to make sure that your app looks like a native one.

Like NPM, Flutter has a cloud package manager which has a good amount of libraries related to accessing native functions of the phone. Most of the libraries are well documented and have examples. Unfortunately, unlike NPM, which is a package manager for any Javascript-based technology, pub.dev is a package manager only for Flutter apps. This presents an advantage over NPM because you find only libraries made specifically for Flutter, that is pub.dev can require specific things for every new library out in the market. For example, before publishing a new library, the owner must specify which OS support if Android, iOS or both. That combined with the huge compatibility of Flutter for most of the devices in the market creates a feeling of confidence when it comes to using a new third-party functionality.

Flutter uses material styled widgets and cupertino style widgets and it’s the developer’s job to ensure that they provide the correctly styled component for Android/iOS. This could be good or bad, depending on how you analyze it. At first glance, you can say that it will imply more work to make sure that your software will look like iOS or Android. However, that could also mean you can create your own custom styles and a more unique identity for your application.

You could have full control of the elements you display. More control means more code, more possible bugs, but greater scalability over time.

Today, most companies aim to ship apps continuously in order to constantly add value to the end customer. In the case of mobile applications, the deployment consists of uploading the app to the store and waiting for an external review that will approve or decline your build. So, if you do not automate the process that builds your app and ships it to the stores, you’re likely to end up having a lot of back and forth effort with poor results. You could upload something to the stores and break some functionality. Or get a build rejected and then review why it was rejected, fix the issues and then upload everything to the stores again. Annoying for sure!

React Native doesn’t have a CI/CD solution for the App Store or Google Play delivery. Third party solutions like Fastlane, Britise, CircleCI, Jenkins among others, are necessary to automate delivery and deployment processes. There’s no official documentation for setting those processes up, but the good part is that a lot of articles explaining the process can be found.

Flutter has a well-documented process to build and deploy applications with no third-party solutions required. Just using Flutter’s rich command line interface allows you to set up CI/CD easily. Therefore, you could fast-forward the deployment of your app to the stores. It also has complete documentation on how to integrate with third party tools if advanced automation is required.

Image for post
Image for post

Hopefully this article will be helpful for you! If you’d like to know more about our experience building React Native and Flutter apps and our mobile development services, feel free to contact us here.

Originally published at https://uruit.com on September 16, 2020.

Digital product development studio for companies that want to challenge their industries.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store