Introducing React Native
Transcript from
React.js Conf 2015 Keynote - Introducing React Native
by Tom Occhino.
When Instagram joined Facebook they had a bunch of projects they wanted to work on, and one of the first ones they wanted to do was Instagram.com.
So they took a look at Facebook's stack and they thought React was really cool and they wanted to use it.
Open Sourcing React
The problem was that at the time React was really really tightly coupled to our Facebook specifics Software stack.
So they wanted to decouple it so they can use it on Instagram and Pete Hunt
convinced us that this is worthwhile.
He actually did most the work to effectively make React Open Sourceable. So at JS Conference 2013 we decided to do just that, and first impressions were pretty skeptical.
What they told us was that we'd taken a "huge step backwards" in terms of the maintainability of our code, simply because we were embedding our markup, our HTML, inside our JavaScript.
But internally it wasn't controversial at all. We had a ton of experience with the syntax because we've been using it for years already, at least four years at the time.
The most important piece about this was that it allowed us to create composite components.
These server composite components wouldn't just send down the network the markup, it was sent down with all of the style and presentation information that you needed, as well as all the JavaScript that made the thing actually do something. But we went one step further than that, we actually made it so you can create components that took in very simple parameters like a viewer and what type of data you want and they would you all the necessary data fetching to make it so that you have a fully functional dynamic component with all the data that it needs just by calling that API.
And then behind the scenes, under the hood there was all sorts of parallelizing of data fetching across components and there was cashing layers and CDNs. But as a client of this component I didn't need to think at any of that. I don't need to worry about how it worked, it worked.
The implementation didn't matter to me, this is a component, this we feel is the proper
Separation of concerns for applications
Facebook was kind of accused of rethinking established best practices, simply because we were storing our markup in our JavaScript. But we actually appreciated it, like finally someone is acknowledging we're rethinking the way that everybody's doing things so perhaps, not coincidentally Pete gave a talk at JS Con and he called the talk
Rethinking best practices
This talk went over a lot of React's principles, its fundamental principles that made it exciting, and it went over a lot of the things that made it powerful.
But if I was asked everyone in this room, individually, what it is that makes react powerful I think I'd probably get a bunch of different answers.
The most common the most obvious one is the Virtual DOM. This is React's claim to fame, this is the thing that kinda set it apart initially and now we have stand-alone Virtual DOM implementations which is awesome.
But another feature that a lot of people called out as being React's most powerful feature was server rendering.
But for people who aren't familiar with React they'd probably call out the descriptive warning messages as the most powerful feature. When you use this framework for the first time and you do something wrong it tells you exactly what you did wrong and how to fix it.
There's also the custom event system and a bunch of other features.
But the thing that makes all these features and more possible is the fact that react replaces imperative mutated API with the declarative API that favors immutability.
When we create our applications using declarative code and when we structure our views declaratively your code is significantly more predictable. The fact you can open up any JavaScript file with the React component in it and understand all of the possible states have that component and exactly how it's gonna behave just by looking at that file is incredibly powerful. And when code is declarative and therefore predictable we can make changes to it more easily with confidence.
Engineers don't need to spend it on a time trying to understand the entire system before they can make a change to one small piece of it.
But the best part I think about being able to make changes the confidence is that when you can change your code more confident the ends up being a lot more reliable.
So I think that React's real power lies in how it makes you structure your code in terms of
React components
The only reason anything like the Virtual DOM or conceptually rendering
on every single update is even possible is because we use React components
rather than trying to force things in the models views and controllers we separate over concerns in the components.
Components are the fundamental building blocks of our application.
What it is about React components though, that makes them different, cause a lot a framework figured this out, we have directives, web components, a lot of other frameworks got it figured out that components are the right separation of concerns but what makes React different well from my experience the difference is that in all those other situations you have to create your component using comparative mutated code but in React you get to describe your component declaratively and I've proposed that the clear code is a lot easier to maintain an easier to extend. And additionally again from my own experience is just a lot more fun.
So we think we really had home run with React we're using everywhere internally everybody loves using the stuff, but the problem is were only using it for web stuff.
We've also got these iOS and Android apps with hundreds of millions of users and we've tried in the past to just build web apps that we could wrap in thin native wrappers. But it doesn't work. The reason that you can't just build a web app and expect it to behave like a native app is because building for the native platform yield a vastly different user experience than building for the browser environment.
In native we have the ability to parallelize work under multiple threads.
We also don't have sophisticated gesture handling, this is another thing that sets native apart on Web.
Another thing we have in native is access to platform-specific capabilities and components. Native widgets are a black box, we don't have access to the source code, we can't see what the parameters are, we don't know what the numbers are that different things that make them feel like they feel and anytime somebody tries to reimplement a native widget using HTML, CSS and JavaScript it always feels like sh*t.
So as much as it pains me to say it, known hate to say it,
The native environment is far more flexible and far more powerful than the browser environment
At least today.
But all that power and flexibility comes with a cost. The native environment is in general far more hostile to developers and to organizations. When we started building a native specific iOS app and a native specific Android app we had to spin up two separate sets of tooling, two separate sets of instructions and all these specific platform code and infrastructure and teams that it wasn't portable.
We couldn't reuse these concepts and not only that, now we have to think about things like memory management and thread concurrency and laying out subviews and also we have to think about things like provisioning profiles for our devices, you can't just load up a browser window anymore, you also can't just push your entire application by saying 'git push', now you have to think about the deployment process.
So it adds an unnecessary overhead in developing applications. And there's another reason it's hard to build native apps. In native, just like with the DOM, you have to use mutative imperative APIs and we've seen this before, whenever we try to build a sophisticated application using those APIs over time as it gets more complicated, and we add more people to the team, this breaks down.
Let's get back to React from the beginning: React has been designed to be able to replace any View system can wrap any imperative View system, it doesn't need to just wrap the DOM. What if we take the exact same React's JavaScript we've been running on Web and we can use it to power truly native applications?
Well that's exactly what we've been working on.
We're calling it
React Native
and we're building it simultaneously for iOS an Android.
Now I'm primarily gonna focus on react iOS today but again we're building it for both platforms.
So the first thing I'm gonna show you here is a very simple Movies app. So this app it literally just lists out movies and you can tap any other movies and see a detailed description of it and you can go back, and this is pretty simple.
I can search for movies.
The things you can't see is when I tap the native status bar this thing scrolls to the top, the native behavior, the other thing you might not notice is as I'm swiping, this is the native navigator, this is actually iOS, these are native components.
The next app I'm gonna show is actually in the App Store.
This is Facebook's Group app. It is actually a combination of native code and React Native code.
We have this multi photo post, you can swipe between photos, put them away, view previous comments here. I'm gonna focus this text box, what happens this is pretty cool when I go to the top of the post I'm no longer in the feed anymore I'm in a permalink view and I can post.
So What was that?
The first thing to note and the most important thing to note is that everything you saw on the screen was completely native, we can't use the web to build an experience like that.
So there was no HTML, there was no browser, there were no web views, but it was completely controlled by JavaScript.
Now there are other frameworks that exist today that scripts native API's in JavaScript.
There's a problem though, the problem with wrapping native is you still have to use these imparative mutative APIs. The only thing that they change is the code that were writing in. So if you just introduced JavaScript naively this could actually end up being a lot worse. If we're naive here we can get into a situation where we're dropping frames in the UI because we're waiting on JavaScript to do some work, for example JavaScript could be running garbage collection, and our main thread is dropping frames. So for going to introduce a JavaScript layer we have to be smart about it, the layer needs to be asynchronous, that way we can do anything we want the JavaScript thread and we won't affect the actual rendering UI, we won't block.
And additionally for perf we should be able to batch up all the instructions we want to execute on native and then execute them whenever we can, so will yield to the main thread whenever we need to.
We know that React diffs subsequent versions of the Virtual DOM so it's perfect for this, we create these diffs, we create these sets of instructions, we throw into a task queue and we execute them in native.
It turns all those imperative API calls, when we're running this on the web, into DOM, set attribute calls and things like that but again there's no reason we have to render to the DOM, so we had to set a primitives on the web <div>
s, <span>
s and <img>
es.
But on the native platform we have a different set of primitives UI Views and Text, Images on iOS, on Android the Android's Views. So we take this task queue, we interpret all these things that came in all the changes that need to be made, it used to be set attribute, Id, set color and now we turn them into imperative native calls.
And this is actually where a lot of the work for React Native when we have these thin wrappers that basically convert those declarative properties into imperative code. But probably the coolest thing about this is that we can take advantage of multi-core architectures a lot better.
By putting a JavaScript in a background thread we can make it so that all of your application logic including your rendering is always executing off of the main thread.
With this architecture we're saying, all your application's code, all of your JavaScript is running off the main thread by default.
So just like when we introduced React a couple years ago, this is working for us, it's in the App Store.
Some people think that since we have this tool at our disposal now we're just going to revert back to having a single code base. I wanna make it very clear that that's not our goal we don't want to have a single code base that powers all our applications, all our platforms, we're not chasing the "Write once - Run anywhere"
pipe dream. These platforms have different looks and feels, different behaviors, and when you're building an Android application you're not thinking about iOS principles, you think about Android.
So instead what we wanna do is chase the
Learn once, Write anywhere
paradigm. We want to be able to develop a consistent set of tools and technologies that let us build applications using the same set of principles across whatever platform we want.
What this means is that a set of engineers can build an iOS app and they can turn around the next day and build the exact same app for Android just by virtue of knowing React. They don't need special IDEs or special environments they can just build using React.
So we're gonna Open Source this soon.
It's still pretty bare-bones but we're adding more to it every day so there's going to be features dropping and landing everything single day.