React Native is the dominant cross-platform mobile framework for React users. It’s powerful, full-featured, and powers many thousands of mobile applications across the iOS and Android landscape. Choosing React Native is a great choice.
You may have heard of NativeScript. It’s a cross-platform, mobile framework for creating truly native mobile applications with JavaScript, TypeScript, Angular, Vue.js, and now React. In our January 6th React Wednesdays show, we had Jamie Birch, the creator and maintainer of React NativeScript to show off the technology and discuss how it works.
How are React Native and NativeScript similar?
Good question, I’m glad I asked it of myself. Both projects let web developers use web skills to create cross-platform mobile applications. Unlike hybrid technology like Cordova, PhoneGap, or Capacitor, React Native and NativeScript produce native apps. This feature means that the application uses the same controls as native applications do. Web developers often face a bit of an adjustment moving to mobile environments. They are surprised to discover that highly optimized controls ship natively with the mobile device. The vendor has tailored these controls for the best use of mobile devices’ limited performance capability.
One example of this is the virtualized list. Android and iOS both ship with the list control that automatically buffers list items that aren’t yet on the visible screen. The buffer functionality means you can have a list of 1,000,000 items, and the memory consumption won’t be negatively affected by this large set of information. As of this article, browsers do not ship with a list component like this at all. Technology that relies on the DOM, like Cordova, PhoneGap, or Capacitor does not use the native controls in this manner, relying on HTML and the DOM for controls.
How are React Native and React NativeScript different?
The first main difference between React Native and NativeScript comes down to the community size. The React Native community is very large. React Native is the default choice for React developers who want to use their React Skills to produce mobile apps. NativeScript has a community as well, but it’s not as large as the React Native community.
The second main difference between React Native and NativeScript is in the architecture. React Native provides a two-thread model: the main thread, on which most native code (including UI updates) runs; and a dedicated “JavaScript thread” on which the majority of the app’s business logic runs. This model helps to ensure mobile apps built with React Native are jank free, though at the expense of making it harder to coordinate the state of the UI with that of the business logic. In NativeScript, everything runs on one thread (like the browser), and it’s up to the developer to ensure their code does not block the frame rendering process.
This design choice has exciting implications for the mobile developer. Because of NativeScript’s design, you can always access all native components from your own JavaScript or TypeScript context. The plugin model is quite simple, leaving a lot of power in the developer’s hands. There’s little need to write bridging code, or native code in most cases, leaving the majority of the mobile application source code in JavaScript (or TypeScript).
React Native, on the other hand, typically requires developers to write bridging code. Being a productive cross-platform React Native developer would mean having a good knowledge of React and at least a passing knowledge of Objective-C (or Swift) and Java (or Kotlin). I always enjoyed writing mobile applications with NativeScript because I didn’t have to stuff more syntax and library awareness inside my already crammed brain.
The Origin Story of React NativeScript
During a NativeScript webinar, Jamie asked whether the NativeScript team had planned to incorporate React. At the time, the NativeScript team had their collective hands’ full building and supporting NativeScript for JavaScript, TypeScript, Angular, and Vue. React, wasn’t “in the budget” proverbially. In an odd twist of fate, TJ VanToll, Developer Advocate for NativeScript at the time, replied to Jamie. The screenshot below almost feels like a family reunion.
In a testament to Jamie’s intelligence and the power of open-source, Jamie took the matter into his own hands and built React NativeScript.
Demonstration of Install and Building an App
At 10:22 of the recording, Jamie started the installation process for React NativeScript. If you are interested to see this process, check out the video. The install was simple, requiring some simple CLI commands to trigger the file downloads and installation procedure.
What’s interesting about React NativeScript is the code used to build a mobile app is the same code you’d use in a web app. Jamie used the React Navigation library in his demonstration application and the source code looked just like it would if it was in a web app. React developers will feel right at home because they can use the libraries and patterns they like, while still getting truly native, cross-platform mobile applications.
A bit about the Native environment
I should clarify my previous statement. React developers can use any library they like with React NativeScript as long as that library is host-agnostic, i.e. “pure React” or specific to React NativeScript. So, for example, libraries that purely manage state (like Redux) or routing libraries (like React Navigation) work fine. But libraries that depend on React DOM (like react-dnd and react-bootstrap) or React Native (like react-native-modal) won’t be directly usable.
That said, React DOM and its whole ecosystem can technically be used within React NativeScript by building a React DOM web app to be run inside NativeScript’s WebView component (building a “hybrid” app). But you wouldn’t want to put your whole app in the WebView; you’d lose the native controls and processing.
For layout, NativeScript has a rich set of components for the user interface. These components range from layout containers, date pickers, buffered list controls, and so on. The controls are all cross-platform. Just declare the component you want and NativeScript will properly invoke the corresponding component on the target device, iOS, or Android.
Which other web technologies does React NativeScript support?
There are many other technologies React developers will find familiar and useful in React NativeScript. Here are some of my favorites:
Flexbox: Flexbox provides an elegant syntax for arranging child components vertically and horizontally. Compared to the way we “used to do this back in the day” Flexbox is a lifesaver for layout out UI elements. Now you can use it on iOS and Android.
CSS: CSS styles elements declaratively. It’s easy to separate styling from component logic, and NativeScript makes it easy. While writing CSS as .css files is supported in React NativeScript, the recommended approach is to declare CSS styles using JavaScript, just like in React Native.
npm Plugins: It’s easy to use the billions of lines of free code available on npm. JavaScript runs in a native runtime on the mobile client. Any JavaScript runnable on modern V8 or WebKit is fair game in your NativeScript app, as long as the code doesn’t have browser dependencies.
Webpack: React NativeScript apps are bundled using Webpack, the most widely used bundler in web development, meaning it’s easy to modify the build process.
How can I get started?
To set up your environment and generate your first project, just follow the React NativeScript documentation website’s Quick Start section.
You’ll quickly want to get familiar with how navigation works, which the docs cover in the Navigation section.
It’s also worth reading up on Native Access to understand the workflow for accessing native APIs in React NativeScript.
And if you’re skeptical about whether NativeScript offers the level of native API access you might need, it’s worth reading a few of these code snippets that demonstrate how easy it is to access iOS native APIs in NativeScript. Jamie has also made some TypeScript playgrounds ready-loaded with iOS and Android SDK typings to show you how the developer experience for using native APIs via TypeScript feels.
For anything else, you can visit the #react channel in the NativeScript Slack or Discord and ask the community for help. Issues can be filed on the React NativeScript GitHub repository.
Which one should I choose?
React Native and React NativeScript both share some similarities: They are both based on TypeScript and React; they are both inspired by Web technologies, and so incorporate CSS, Flexbox, and Hot Module Replacement; and they both produce fully native iOS and Android apps.
React Native is a strong choice in general simply due to its maturity and mainstream adoption, being backed by Facebook, Microsoft, Amazon, and other large companies. It covers non-mobile platforms (e.g. Web, tvOS, macOS, Windows, and more – though all in different states of maturity). It’s also suitable for creating “brownfield” apps, e.g. augmenting an iOS app with a few new screens that happen to be cross-platform with Android.
By contrast, React NativeScript specializes in seamless native API access: Native code changes made from the JavaScript context can be hot-reloaded, allowing for rapid adjustment of designs; Trivial API accesses (e.g. checking the battery level, sharing a link, composing an email, etc.) can be written in-context as snippets of JavaScript, rather than stopping to install a native module and recompile the app; and native APIs are accessed synchronously, allowing you to write your app logic in much the same way you’d write a native app, rather than having to sequence chains of Promises.
Whichever the choice, if you’re already accustomed to React DOM, it should be easy to adjust!