Starting with Flutter (from React Native)
At the end of 2018/start of 2019 I wanted to fill in my knowledge of modern UI approaches. I have worked with native iOS and Android and more recently largely with React and React Native. The gaps I wanted to fill in were MacOS (native), Electron and Flutter which I'll report on here.
tl;dr: I was very impressed. Flutter feels like Google looked at React Native, liked the core ideas but thought it was a massive series of hacks (it is, for better and worse!) and ordered a bunch of smart people to build something similar from scratch. (I think that is nearly true, except they actually repurposed their Dart programming language and Skia library for it.)
The documentation is great (such a contrast with doing MacOS native development which I was doing around the same time, where the documentations is awful).
It allows you to build fully React-ive user interfaces, cleanly separating state and view. The hot reloading seems to be a lot more robust than React Native's version. Debugging view hierarchies and so on is great with first class tooling built into IntelliJ (or Android Studio).
Code completion/editing is generally great though I'm not a big fan of Dart. It is okay but it doesn't really like you doing functional programming. The lack of algebraic data types along the lines of Kotlin's Sealed classes, TypeScript's discriminated unions or Swift's enums is frustrating. Also sometimes the compiler seems to miss things that you would expect it to catch. You often have to create many classes where in other platforms/systems a single function would suffice. Tuples would also be nice. Though if you are coming from Java, Dart will likely seem amazing! (But semicolons, why? Does the Dart team hate us? It is 2019!)
Flutter really likes Widgets, using them for many things that e.g. React Native would use styles for. This can lead to extremely nested, verbose code. To be honest I can't tell if this is that bad, it looks ugly but so did JSX for the first few days. Some things are a bit annoying and lead to seemingly unnecessary code duplication: stateless widgets would be a function in React (Native) but in Flutter they are a class: so you have to declare members, pass in to a constructor (albeit with a shorthand syntax) and then use again in your build method. Stateful Widgets are worse: you actually create two classes for some reason that I don't entirely follow (explanations seem to suggest this is required for reuse at runtime/good for hot reloading). For styling well there isn't any: you can have themes and set various properties on widgets/via nesting widgets, but it doesn't have a thing analogous to React Native's StyleSheets.
Performance appears to be great, as promised. I tested on a five year old Android device that often struggles with native Android apps, and it worked well. If anything some things seemed to be a bit smoother than my iPhone X but that may be because Android's animations are set up to disguise dropped frames near the start of a transition.
What I built: Modern Colour Picker
I generally don't think you can evaluate an approach until you ship it (even if you ship something small in it). I made and shipped Modern Colour Picker to both iOS and Android. The App uses Material Design, uses code generation for JSON persistence. The only native code is on iOS where I wrote some custom code for sharing (on Android I didn't have to).
When should you choose Flutter and/or React Native
Maybe favour Flutter if:
- You want to be able to create custom animations and graphics code
- Performance is a concern e.g. older Android devices
- You don't have a designer and are willing to use the (great) Material design 2.0 implementation
- You know Dart already (that seems unlikely)
- Android is a priority (while React Native has improved here it is definitely weaker, I found Flutter on Android to seemingly outperform regular Native Android)
Maybe favour React Native if:
- You are working with a content heavy JSON or GraphQL API
- You have a custom look and feel you want to achieve (possibly from a dedicated designer)
- You know React (and/or have a web version to support). Please don't try to make the same code run on both mobile and web; React is learn once, write everywhere (but that is for another article)!
- iOS is a priority
In many areas Flutter exceeds React Native. It is way more polished and straightforwardly performant. The tooling is great. So switch? Maybe, but actually for most Apps I think either will work great. Both do fully Reactive UI, something which outside the web appears to be hard to find.
My conclusion from just a few days of Flutter is actually that native app development is probably moribund for most purposes: now that you can do straightforward cross platform highly custom animations that addresses (let's make up numbers) 10% or whatever of use cases that React Native struggles with. Perhaps there is still a small percentage of use cases left (making something up, let's say: 5%) that need individual native implementations. Flutter and React Native are both at the point that they are often better choices for a single platform (due to reactive UI, fast iteration with hot/live reload), never mind that they can do both major mobile platforms.
SwiftUI and Jetpack Compose might change this picture, but both are extremely early at time of writing (and SwiftUI only supports iOS 13+ etc so isn't going to be viable for many use cases for over two years).