Learn the fundamental differences between Flutter and React Native, plus get a clear guide on which to pick based on your scenario.
Flutter vs React Native Series
1. Flutter vs React Native: The Core Differences
2. Flutter vs React Native: Part Two
3. Flutter vs React Native: Part Three
By reading this series, you can expect to learn the fundamental differences between Flutter and React Native.
Understanding how cross-platform can be achieved will help you grasp how Flutter compares to React Native.
How it has been historically achieved
Everything is rendered to a screen using a lower-level graphics language.
To abstract away the lower level rendering of elements, original equipment manufacturers provide you with an SDK to build your user interface.
Cross-platform normalizes the different ways to render a user interface by providing you with an API that abstracts away the details of rendering in different environments.
As an example, take the environment of an iOS app. You can choose to use their UI SDK UIKit, or you can use a lower-level rendering API called Metal. Android will use different rendering APIs and thus if you want a cross-platform interface your API will need to communicate with each platform's rendering mechanism.
The divergence in cross-platform solutions happens at two levels. The first level is the programming language, which one they choose to use. The second level is the rendering level, which layer they choose to access.
At the rendering layer, cross-platform frameworks can choose to use something lower level like graphics APIs (Metal, Skia, OpenGL) or use the provided UI SDK like UIKit on iOS and Android Jetpack on Android.
- Xamarin does UI SDK binding and uses C# - a compiled language.
- QT has its own rendering engine built with OpenGL and uses C++.
- Tauri (New on the block) uses Webview, a tiny cross-platform webview implementation. It allows multiple languages to drive logic, as long as HTML & CSS are used for rendering.
- Chromium renders to the page using its own rendering engine.
Each decision on how you achieve cross-platform will yield a different drawback. In the end, there is no one solution to rule them all - they all just have different balances.
The core differences between Flutter & React Native
The core differences between Flutter and React Native lie in the languages of choice and rendering strategies.
At the rendering level, Flutter chooses to go lower level and implement their own rendering engine on top of Skia. React Native binds to the OEM's UI widgets by translating React Components into their native counterparts.
These core differences pretty much dictate the main pros and cons of each solution. The pros and cons related to these two core differences won't be changed unless they revert the architectural decision, which they are likely to not change.
This is not to say that there are no other pros and cons. There are, specifically around tooling, SDK quality, and overall developer experience. The thing is, these other elements can be continuously changed or improved. As an example of such, when Flutter released its version 1 highlighting its "hot reload" feature, React Native already had this feature for years, but it degraded to a point of un-usability. But, months after Flutter's V1 release React Native fixed its "hot reload" feature.
Upcoming articles to this series will cover the remaining pros and cons not related to the core differences.
Differences between the language of choice
Interpreted languages have the benefit of being more flexible, offering more features like dynamic typing and smaller program size.
It is important to highlight that while compiled languages can be naturally faster, for a common user of your application this is not perceptible. You will see what I mean in the last portion of this post.
Differences between the rendering of choice
The UI will be different and the runtime costs too.
When you use a OEM provided UI element you inherit its default styles and behavior. When you don't use a OEM provided UI element, you define the default styles and behavior. There are pros and cons to both approaches.
One of the benefits of using a provided OEM UI element is you have a lot of work done for you, especially around behavior. Whenever there is a version update, you benefit from the thousands of hours that platform puts into these UI elements, perfecting the behavior and look.
Whenever someone says "have a native look and feel" they mean looking and behaving like the other native apps using the provided OEM UI.
A drawback to using OEM UI is that each platform will look and behave differently. For cross-platform, this is an architectural decision you must make. Do you want your UI elements to be exactly alike independent of the platform? Or do you want the UI to look native, similar to the OEM UI?
While it does seem rational to say we want the UI to look the same across any platform, design teams don't always agree. As a result, Flutter tries to mimic the targeted platforms native UI behavior and feel by offering themed UI kits.
Having lower-level control of rendering allows for more possibilities. We need to understand that the provided OEM UI elements weren't ever intended to be used for intensive graphics activity. You shouldn't code a game using UIKit. Games or any other intensive graphics activity is done by using lower-level rendering APIs like OpenGL.
I would argue that Flutter does lower-level rendering for three reasons: a) to have fine control over how things look across all platforms, b) be easily expandable into other platforms, and c) to guarantee higher frames per second.
Flutter's architectural decision to do lower-level rendering with Skia makes it easier for it to expand to new platforms. All they need to do is make sure the new target supports the Skia back-end - which they usually do since it leverages OpenGL.
The guarantee of higher frames per second can be overkill. The thing is, most apps operate at 60FPS without any optimizations. This is because they are not doing anything intensive. This becomes more of a concern when you are doing very intensive animations.
I don't have a single app on my phone that has an intensive UI animation that would require lower-level rendering. And Flutter's first announcement around how it could achieve 120fps felt unnecessary for the common purpose of 2D UIs.
When it comes to 2D UIs, the final outcomes will look great for either solution you use.
As you can see, these two apps are performant and look great. While Flutter can achieve higher performance due to its fundamentals, this performance will only be relevant for very UI intensive operations that are rare for a 2D app.
So far, I’ve covered that what differentiates Flutter from React Native will be the final UI look and feel. Plus, your preferences around the language used for development also come into play.
To further explore the differences between not only the language but also the patterns and mental models to build UIs, we want to see samples of how code will look when we use each framework. Read Flutter vs React Native: Part Two and Part Three.
- Flutter Engine
- Compiled Versus Interpreted Languages
- API called Metal
- Tiny Webview