React-Native vs Xamarin (Forms)... Which should I choose?

tl;dr: It's complicated.

You didn't think it'd be that easy did you? :) I realise I'm being a little cheeky with that tl;dr, but it honestly is complicated.

There's a few things to talk about when making a choice between React-Native and Xamarin (Forms):

  1. The general philosophy in how the framework tackles cross-platform applications.
  2. Language support
  3. Platform support
  4. The tooling and general developer experience.
  5. Third-party ecosystem.
  6. Feature development.
  7. Continuous Integration and Deployment.
  8. Supportability.

Caveats

  • You may be wondering why every time I write Xamarin, I'm writing Xamarin (Forms). This is because all of my experience with Xamarin has come hand-in-hand with Xamarin Forms, so all of my writings here are coloured with that perception (or bias).

Lets dig in!


General Philosophy

This might be an odd thing to start with, but I think it's important for establishing context in how each framework seems to approach cross-platform development. I think if you can understand this, it's easier to understand the trade-offs involved in picking one framework over another.

Xamarin (Forms)

Xamarin is Microsoft's tool for developing cross-platform applications. I feel like Xamarin's approach to cross-platform development is this at its core:

Abstract away as much of the native platforms as possible behind a .NET Layer

The best thing about this is it lets developers who have no experience in the native mobile development landscapes, jump in and write an application that can be deployed to quite a few platforms (more on this later).

The drawback (in my Opinion™) with Xamarin is the feature development experience is less than ideal. It's like they've spent most of their energy focusing on the fact you will never need to dive down into Android or iOS with any depth, and they've done this really, really well. As per the caveat in the intro; I haven't done any of the "native" Xamarin development, creating Storyboards, or pure Android views and the like. My experience with Xamarin comes hand-in-hand with Xamarin Forms, but I think the general point stands1.

React-Native

React-Native is Facebook's answer to cross-platform development. The approach to my mind by Facebook is:

Let React make us lightning quick at writing new features

And it really is lightning quick at features. More on this later.

The main drawback I've found with React-Native's approach is you're much closer (like, cheek-to-cheek) with the native platforms. You might not think this is a big deal initially, but if you're a .NET practice looking into React-Native, you may want to take a look at this post I did after my first React-Native project, me being a .NET Dev primarily. If you're already experienced in the native space this may not be a big deal to you, and if so, wonderful!

The main native concerns you deal with in React-Native - specifically around build tools and external dependencies - are still fairly rough around the edges in my opinion. From differences in underlying SDK dependencies to build processes themselves differing between the React-Native CLI and the native IDEs (which you'll also need to spend some time in), to me I still think React-Native needs some more time to mature in this space.


Language Support

Xamarin

Out of the box, Xamarin supports C#, VB.NET and F#, using XAML for its for its views mostly (especially in the Xamarin Forms space). This gives you an incredible amount of flexibility in terms of how you build your application as each of these languages supports a huge variety of ways of working... Object Oriented Programming, Functional Programming, and all of the various well-established patterns that dwell within those disciplines.

React-Native

On the surface React-Native is mainly a JavaScript platform, with TypeScript if you really like type safety (and you should, imo). It uses React-like syntax for defining its views (RN likes the term "Component"). It has a few quirks of difference between "normal" React and React-Native, but they're quite similar.

Under the hood is where things start to get interesting.

React-Native uses pre-built implementations of native projects, which means while on the surface you've got JavaScript, underneath its actually running Java (for Android) and ObjectiveC (for iOS). This means any quirks with those languages you end up inheriting as part of the project. This is the same with any language, to be honest, but unlike Xamarin where it's mostly one variant of a language you'll be using, React-Native becomes more complex in that you need to worry about JavaScript, ObjectiveC and Java. And if you're doing something complex with your app, you'll definitely need to delve into those last two at some point.


Platform Support

Xamarin

Xamarin supports Android, iOS, and UWP, right from when you go File -> New Project.

React-Native

"Vanilla" React-Native supports Android and iOS out of the box. There's no native (ha) support for UWP, however if you take a look at react-native-windows, run by the folks at Microsoft, they've made a pretty good start there. I haven't looked at this, so I'm not sure how stable it is.


The tooling and general developer experience

Xamarin

Xamarin development is done primarily through Visual Studio (and Visual Studio for Mac on MacOS). Visual Studio on Windows is great, however Visual Studio for Mac still has a long way to go in my opinion before I'd consider using it on a full-time basis. I've encountered many bugs, performance issues, and general frustrations with how the IDE is laid out. Its fairly different to Windows' Visual Studio. Amusingly, it seems Xamarin is the inverse of my experience with React-Native on Windows as Xamarin is extremely Windows focused.

Thankfully Xamarin now allows you to connect to a remote simulator or device from your Windows PC. You still need the Mac, as it serves as the build agent for the iOS components of your solution and the host for the simulator, but aside from that it works great.

The main pain point with Xamarin though, can come from bugs during compilation time with Visual Studio. You'll likely encounter times where your builds don't seem to be coming through to your device/simulator correctly, or where builds fail where DLLs get locked. A few months back I also had some issues trying to upgrade a solution to .NET Standard, and hit some really nasty dependency resolution issues. These have apparently been fixed, but it's something to be wary of, especially if you plan on targeting .NET Standard (or even migrating an existing solution to .NET Standard).

Build times on Xamarin can also be pretty frustrating. It uses MSBuild under the hood to compile any PCL libraries, as well as the native Android components to IL, which is then packaged with Mono. iOS code is compiled using MSBuild, straight to ARM Assembly (!), and Apple is fairly strict on where you can build its products (yay licensing) so you still need a Mac. If you want to read more (and I think you should as it's really fascinating), I'd check out this, this and this on the MS docs where it goes into far more detail.

React-Native

React-Native has one massive point in its favour when it comes to the general developer experience, that of hot reload/live reload used closely in conjunction with the JavaScript you write. Honestly, this is life changing, especially if you're used to long build times like with Xamarin. However if you change anything in the native space, you'll need a full rebuild from the CLI/IDE.

IDE support for React-Native is anything that serves as a text editor, at least for the JavaScript components. My main tool of choice would be VSCode, as there are some fairly useful extensions out there specifically related to React-Native. It uses a Node process to package your JavaScript and send it on the fly to the device/simulator which comes with the usual caveats around Node. Its fairly quick, though I've noticed once it finds an exception sometimes it'll make the process unresponsive and you'll be scratching your head to try and figure out why nothing is working. A simple restart will fix this.

You'll also need to deal frequently with the native IDEs, XCode (for iOS) and Android Studio (for Android). These come with their own quirks and frustrations, and I'd recommend reading up on them before starting a React-Native project.

In addition to this, you're also going to be dealing with the native build tools, that being XCode (iOS) and Gradle (Android). There's a lot here, and it's completely different to how we build and manage JavaScript. It is also significantly more complex, so it's something to be wary of when making the choice of React-Native.


Third-party ecosystem

This section mainly focuses around the open-source aspect of each of the native ecosystems. You may have more luck (with both of these frameworks) using paid libraries, but most developers will focus on open-source libraries and components.

Xamarin

The third-party ecosystem for Xamarin is really healthy, and is served mostly via NuGet. You'll come across the odd abandoned project, but for the most part they're normally very active. They're also (obviously) all .NET, so they'll pretty much always work in your project with a simple dotnet add package [package-name]. You may need to do some extra setup, but even that is normally done with .NET classes and methods (as opposed to having to delve into Java and ObjectiveC in React-Native), which is normally straightforward and well documented.

There's also a decent amount of variety, which is important as most packages in the OSS community come with tradeoffs, so you've got options if something doesn't quite fit the bill.

React-Native

Hmmm. I have some complicated... feelings... with regards to my thoughts on the React-Native ecosystem. This is one area that React-Native really suffers in my opinion, due to several factors:

  • Abandoned projects
  • Complex linking processes between JavaScript and Native Code
  • Reliance on sometimes arbitrary native code, which wont always work/integrate the way you expect with other libraries (ie. Java and ObjectiveC)
  • Underlying dependency issues

I'm not going to go too in-depth with this, as the two posts linked above cover it fairly well. To be fair: there are some really good, fully featured libraries out there in the React-Native space, but the added complexities some of those libraries introduce make it really painful, both from initial integration in your application and potential supportability later on in your application's life.


Feature Development

Xamarin

Here is where things can get a little tricky for Xamarin. Feature development in Xamarin is mainly driven by a combination of C# (for logic), and XAML (for Views).

The C# is completely fine, but XAML is a complicated beast. A few things to note;

  • Styling XAML (and Xamarin in general tbh) can be really painful, especially if you want a consistent visual experience between the two main platforms, Android and iOS.
  • The variant of XAML that Xamarin uses is different to the variants used by UWP and WPF. This means you'll potentially hit some arbitrary limitations, or have to work around these if you're expecting the same level of power that you get in WPF XAML. Thankfully, there is movement towards a unified XAML implementation across the various technologies that use it, but as of writing this is in preview.
React-Native

I'm trying not to make this post a death-match between the two technologies, establishing a clear winner by the end of it. However, if you were making this post a competition, React-Native would win in this space. Provided all the relevant native concerns get out of the way feature development is a breeze. You've got;

  • Live reload/hot reload
  • CSS-style syntax for layout and styling
  • A consistent visual experience between platforms
  • Easier code re-use

React-Native's feature development is a different way of thinking (to my mind at least), than Xamarin. How you structure your components and how you re-use them is a slight shift in thinking compared to Xamarin XAML features. With Xamarin you're more likely to have large overall "Pages", whereas React-Native seems to encourage you to think down a deeper level. This means you can get better code re-use. You can definitely apply this same way of thinking to Xamarin, but I feel like React-Native makes this style of UI design easier, in terms of how quickly you can import and use your components.


Continuous Integration and Deployment

Xamarin

As Xamarin does such a good job of abstracting away the native dependencies, CI is straightforward. You'll set up your pipeline to build the respective platform's project and you'll use whatever task hooks into MSBuild. You'll still need to ensure whatever build agent you use has the respective Android and iOS SDKs, but its mostly pain-free, at least in my experience.

For deployments, your best bet is AppCenter2. This is Microsoft's attempt to be a one-stop shop for all your Mobile Development needs. It comes with a hosted pipeline for use to use for building the application, while providing a set of fairly powerful integrations with the relevant native platform App Stores, as well as Intune, a business-focused device management tool that also manages corporate apps. So if this is high on your priority list, this is a good way to go. You can always upload apps to this without the use of AppCenter (VSTS, for example, has tasks that can push to Intune) but the integration provided is really clean and easy to set up.

React-Native

CI is a little complicated in React-Native, as you've got a few steps to think of when building your application in your pipeline.

  • Preparing the React-Native JavaScript bundle
  • Building the Gradle project, which generates the APK
  • Building the XCode project, which generates the IPA.

As these are all hooking into very distinct, sometimes native concerns, it means you can run into quite a bit of trouble. You'll need to get used to understanding the build output of each of these components, and troubleshoot where necessary. Thankfully, these are all well-documented but if you're going in blind (like I was) you may be in for a bad time.

In terms of deployment I'd look (again!) at AppCenter, which also covers React-Native! Most of the points with regards too AppCenter in the Xamarin section above stand here too, so I'm not going to rehash it.

I'm not sure how much support there is for Intune, when compared to Xamarin. Xamarin has dedicated libraries to integrate with Intune and is a first-class citizen. There is a React-Native library out there that looks like it may get you off to a good start, but it hasn't been touched in a while so it may be abandoned. This doesn't look like it's supported by Microsoft either. You may be able to get away with basic functionality, as Intune supports the upload of any APK or IPA.


Supportability

To be clear, supportability in this context means the probable lifetime of the platform, and how easy/difficult it is to get assistance on issues that may arise during the development (or general support) of your application.

Xamarin

Xamarin is supported by Microsoft, which to my mind is a big deal in the context of supportability. Microsoft made a decent amount of noise in bringing Xamarin into the fold in 2016, so you can bet this is a long term play by Microsoft to get a decent foothold in the cross-platform space. So I think Xamarin will be around for a long time. You can check out the Xamarin Forms Roadmap here. The only thing left in the "core" Xamarin space (as far as I'm aware) would be adding in more APIs that didn't make the cut initially and introducing any new APIs as the core native platforms introduce new functionality down the track.

You also get language support through the usages of F#, C#, VB.NET and XAML, so if you hit any weird and wonderful issues you're quite likely to be able to reach out directly to Microsoft for assistance. And failing that, you've got the usual resources like Stack Overflow, Twitter and the host of MS blogs that operate in this space, outlining things like direction, intention and current state of affairs.

React-Native

React-Native is supported by Facebook, who were also the original creators of the platform. They've spent quite a bit of time and money investing in this platform (as well as React itself) and it doesn't look like they're slowing down any time soon. They're quite active on the React-Native GitHub repository. I couldn't find a proper roadmap as such for React-Native, as you're referred to the blog for an idea of what they're thinking and where they're heading. It does look fairly active so that's a good sign.

From a language perspective, you're in JavaScript territory from a feature perspective, and then ObjectiveC and Java in the native space.

React-Native generates its native projects with ObjectiveC and Java, and given Kotlin and Swift have been around for a while it looks like eventually the project will get ported to the newer languages, but there's no guarantee. Until then, you're stuck with the quirks and complexity of each (especially ObjectiveC). Upgrading these projects would also potentially be problematic, due to the complexities around dependency management.

If you plan on starting a React-Native project, I would strongly recommend a stricter typing system than pure JavaScript, as this will help your project in the long term for maintainability. You've got a two main options;

Either one is good, but I prefer TypeScript as it's also supported by Microsoft, who actively add features on a regular basis. If you want more info on this you can check out this blog post on the React-Native blog.

Conclusion

So you may be wondering... "Which should I choose"? And the answer is honestly "it depends". This post was meant to highlight each of the benefits/trade-offs you may encounter when looking at each of these platforms so you can make an informed decision of which platform is best for your application/company in the long term.

However, if you were to give me no wiggle room, this is what I'd respond with:

  1. If you've got no native mobile experience, and you're a .NET practice, building an app with reasonably tight deadlines, I'd go with Xamarin as it closely aligns with your existing skill-set. The learning curve for React-Native is steep, and unless you've got a safe environment to fail (because you might), React-Native is a huge risk.
  2. If you've got a decent amount of native experience, I feel like React-Native is a better choice overall. General feature development is super quick, and provided you're willing to cop the tradeoffs above you're probably in a good space to get something shipped fairly quickly. The ecosystem is less of a big deal, provided you're willing to write your own native code where necessary.

The reason I didn't put these points in the tl;dr is because these sorts of decisions require context if you want to make the best decision possible. Knowing the tradeoffs for a decision like this is important because the impact of this decision can cause years of pain down the track (not to mention months of pain up front). Even knowing the context now, the points above may not be directly applicable and you may need to make a different choice based on a slightly different situation.

Obviously this is just my opinion, so take it with a grain of salt :)

Hopefully this has helped you make a decision (or at least better understand what you're potentially getting yourself into!) on choosing a cross-platform technology. As always reach out Twitter if there's anything you think I've missed or misunderstood.

1. Feel free to yell at me politely on [Twitter](https://twitter.com/arggrande) if you disagree. 2. While AppCenter is amazing, I'd avoid using it for testing with external users to your organisation. There are quite a few steps involved in the initial sign-up process (which can be scary for your potential users). Mobile browser support is fairly limited, so phones like the Samsung Galaxy range will have trouble, you'll actually need to download Chrome and use that instead of the Samsung browser. AppCenter is still in its early days too, so this will likely change over time.