Mobile app development 5-10 years ago was awfully painful. Quite simply, the infrastructure of a mobile app in java, kotlin, c#, objective-c and swift was way too complicated. In addition to that, 2 different codebases were required for a single app - 1 for android and the other for ios. This often resulted in employers recruiting 2 different teams for one app, which drastically increased the cost of production.
However, in recent years, that trend has changed. With the advent of the chromium v8 engine, the industry has shifted. Javascript has become increasingly popular as it can now be used almost everywhere. With javascript running out of the browser, developers were able to create hybrid apps which are essentially web apps running in a native style, without the browser features.
React native
In 2013, some Facebook developers pitched the project react-native in a hackathon. From there, it grew as an internal project. Then in 2015 in a react.js press conference, react native was announced.
React native is a javascript framework, which allows developers to build native apps in javascript for both ios and android. It utilizes a javascript engine that executes the code on runtime. So the app is not entirely native since a javascript bridge is used, however the core components are rendered natively.
Flutter
More newer to the scene is Flutter. Flutter is a software development kit made by Google to create cross platform apps in ios, android, linux, macos and windows. Essentially, a single codebase can be used for 5 different platforms, assuming that macos and ios are 2 different platforms (which it is!).
React-native vs Flutter
It must be noted that none of the aforementioned tools is superior to the other. It entirely depends on use cases and often boils down to the developer's preferences. So, let us compare the 2 frameworks or toolkits.
One of the most obvious differences is that react-native is more well maintained as it has been around for longer, and the developers are heavily invested in the framework. Compared to flutter, even though Google is just as invested in flutter, it is relatively new so it is prone to more issues.
React native is a javascript framework whereas flutter is a dart framework, which is a programming language developed by none other than Google. Hence, react-native is easier to pick up as javascript is more popular, even though dart is also not that different from javascript (Lets be honest, for a true developer, almost every programming language shouldn't be a problem to pick up).
React native has a native UI thread and a javascript logic thread. A bridge is used in runtime to connect the UI thread and the logic thread. So the UI of javascript is not exactly native. So heavier apps can be slower and sluggish if the logic thread fails to execute within 16.67ms, which can result in a frame drop. Flutter on the other hand compiles the widget entirely to native code so it is more fluid.
Even though react native apps have a bundle size larger than native apps, it is often smaller than the bundle size of Flutter apps since react-native is more optimized, and with the hermes engine, it can be even smaller.
This is my personal opinion, so it should be taken with a grain of salt. React native codebase is more neater than that of Flutter's since react native uses components, which can then be broken down to individual components and all the components can be structured accordingly. Flutter on the hand utilizes widgets, which is almost the equivalent of a component but it is way more complicated to use and it is often nested a lot which can be hard for newer developers to read the code.
In conclusion, it can be deduced that react native is a better choice for developers who are already comfortable with javascript and are looking for stability. However, for more fluid UI, flutter just might be the better choice.