There are some subtle architectural differences between Flutter and React Native.
Flutter compiles down to native code, so it's much more akin to a game engine like Unreal or Unity where you ship everything with the app. This shows in its performance.
Reasons to choose Flutter
- Design friendly
- Greenfield development
- Company lead
- Language is the code
Flutter compiles to native code. Unlike most cross-platform solutions there is no bridge (even when making native plugins), which is the top bottleneck for performance. This performance does come at the cost of larger bundle sizes on average. In non-real world tests, Flutter has shown itself to perform very well. Regardless, you can write code that runs well with RN or runs poorly with Flutter.
Flutter has a deep widget library that ranges from low-level to platform level. This means you can build an Android application that looks like it belongs, but if you want to build a completely custom design you can do that as well.
Animations are built into the core of the framework. Also, Flutter allows you to use Animated images thru Flare.
Although flutter is open-source, the majority of the framework development is lead by Google. They have several teams dedicated to Flutter development and developer relations. This is not a knock on RN so much as it is a hat tip to the teams behind Flutter. They regularly survey the community to determine the direction of Flutter and Dart.
Language is the code
There is a very strong coupling between Dart and Flutter. The language is essentially being built for front-end development in the same way that Swift and Swift UI are being tailored towards Apple development. There is a lot of strength in being able to direct a language towards a specific focus. Dart has improved the language several times to accommodate Flutter developers and the language design spec is available on github.com and welcomes contributions.
In my experience of using both, Flutter is faster and less buggy. Let me repeat the in my experience part. Hot reload and hot refresh exist in both, but Flutter has a clear advantage in speed and consistency. It's pretty common to see screens of death starting up "Hello World" examples in React Native. In Flutter, you almost always see them when you have done something wrong. Also, because Dart is strongly typed it appears the errors are a bit more meaningful. You can get static type analysis thru TypeScript (which I love), but dynamic, runtime analysis is where Dart shines.
Reasons to choose React Native
- Larger community
- Code push
- Targets more platforms (currently)
- Community driven
- Brownfield development
React Native can currently target every desktop, mobile device, and web. Flutter has some efforts beyond mobile but they are still a ways off.
More efforts are community driven in RN, which is a testament to it's popularity. Whether you believe that's a good or bad thing depends on your faith in open source.
The story for Flutter in brownfield development is still in its fledgling state. It was very much built first for greenfield. To my knowledge, RN on the other hand was built specifically for the need of adhoc adding components into existing apps, so it makes sense that they'd have a better story.
People with more experience can chime in further or correct any of these points. I have tried to represent the differences as fairly as possible.