From 9f74f8b659f7bb7eabf4efbafcc5b47edf7e80c9 Mon Sep 17 00:00:00 2001 From: Website Deployment Script Date: Tue, 30 May 2017 22:56:52 +0000 Subject: [PATCH] Updated docs for next --- .../2016/03/24/introducing-hot-reloading.html | 52 +-- .../07/06/toward-better-documentation.html | 22 +- .../12/react-native-meetup-san-francisco.html | 2 +- ...to-left-support-for-react-native-apps.html | 58 ++-- .../exponent-talks-unraveling-navigation.html | 2 +- ...headless-js-the-keyboard-api-and-more.html | 16 +- ...cing-button-yarn-and-a-public-roadmap.html | 2 +- blog/2016/12/05/easier-upgrades.html | 26 +- blog/2017/01/07/monthly-release-cadence.html | 2 +- .../14/using-native-driver-for-animated.html | 26 +- blog/2017/03/13/better-list-views.html | 34 +- .../03/13/idx-the-existential-function.html | 8 +- .../introducing-create-react-native-app.html | 2 +- blog/index.html | 2 +- releases/next/css/prism.css | 139 ++++++++ releases/next/docs/accessibility.html | 58 ++-- releases/next/docs/accessibilityinfo.html | 34 +- releases/next/docs/actionsheetios.html | 2 +- releases/next/docs/activityindicator.html | 2 +- releases/next/docs/adsupportios.html | 2 +- releases/next/docs/alert.html | 10 +- releases/next/docs/alertios.html | 24 +- .../docs/android-building-from-source.html | 22 +- releases/next/docs/animated.html | 49 +-- releases/next/docs/animations.html | 130 ++++---- releases/next/docs/appregistry.html | 2 +- releases/next/docs/appstate.html | 28 +- releases/next/docs/asyncstorage.html | 44 +-- releases/next/docs/backandroid.html | 2 +- releases/next/docs/backhandler.html | 8 +- releases/next/docs/building-for-apple-tv.html | 44 +-- releases/next/docs/button.html | 4 +- releases/next/docs/cameraroll.html | 2 +- releases/next/docs/clipboard.html | 8 +- releases/next/docs/colors.html | 2 +- releases/next/docs/communication-ios.html | 38 +-- releases/next/docs/datepickerandroid.html | 8 +- releases/next/docs/datepickerios.html | 2 +- releases/next/docs/debugging.html | 18 +- releases/next/docs/dimensions.html | 2 +- releases/next/docs/direct-manipulation.html | 114 +++---- releases/next/docs/drawerlayoutandroid.html | 26 +- releases/next/docs/easing.html | 2 +- releases/next/docs/flatlist.html | 58 ++-- releases/next/docs/flexbox.html | 56 ++-- releases/next/docs/geolocation.html | 2 +- .../next/docs/gesture-responder-system.html | 2 +- releases/next/docs/getting-started.html | 115 ++----- releases/next/docs/handling-text-input.html | 30 +- releases/next/docs/handling-touches.html | 14 +- releases/next/docs/headless-js-android.html | 10 +- releases/next/docs/height-and-width.html | 38 +-- releases/next/docs/image.html | 46 +-- releases/next/docs/imageeditor.html | 2 +- releases/next/docs/imagepickerios.html | 2 +- releases/next/docs/images.html | 26 +- releases/next/docs/imagestore.html | 2 +- .../docs/integration-with-existing-apps.html | 296 +++++++----------- releases/next/docs/interactionmanager.html | 8 +- .../next/docs/javascript-environment.html | 2 +- releases/next/docs/keyboard.html | 24 +- releases/next/docs/keyboardavoidingview.html | 2 +- releases/next/docs/layout-props.html | 2 +- releases/next/docs/layoutanimation.html | 4 +- releases/next/docs/linking-libraries-ios.html | 6 +- releases/next/docs/linking.html | 42 +-- releases/next/docs/listview.html | 18 +- releases/next/docs/listviewdatasource.html | 14 +- releases/next/docs/modal.html | 50 +-- releases/next/docs/more-resources.html | 2 +- .../next/docs/native-components-android.html | 64 ++-- releases/next/docs/native-components-ios.html | 174 +++++----- .../next/docs/native-modules-android.html | 204 ++++++------ releases/next/docs/native-modules-ios.html | 156 ++++----- releases/next/docs/nativemethodsmixin.html | 45 +-- releases/next/docs/navigation.html | 58 ++-- releases/next/docs/navigatorios.html | 76 ++--- releases/next/docs/netinfo.html | 36 +-- releases/next/docs/network.html | 98 +++--- releases/next/docs/panresponder.html | 28 +- releases/next/docs/performance.html | 18 +- releases/next/docs/permissionsandroid.html | 12 +- releases/next/docs/picker.html | 10 +- releases/next/docs/pickerios.html | 2 +- releases/next/docs/pixelratio.html | 10 +- .../next/docs/platform-specific-code.html | 24 +- releases/next/docs/progressbarandroid.html | 10 +- releases/next/docs/progressviewios.html | 2 +- releases/next/docs/props.html | 40 +-- releases/next/docs/pushnotificationios.html | 16 +- releases/next/docs/refreshcontrol.html | 32 +- releases/next/docs/running-on-device.html | 210 ++++++------- .../next/docs/running-on-simulator-ios.html | 2 +- releases/next/docs/scrollview.html | 14 +- releases/next/docs/sectionlist.html | 30 +- releases/next/docs/segmentedcontrolios.html | 8 +- releases/next/docs/settings.html | 2 +- releases/next/docs/shadow-props.html | 2 +- releases/next/docs/share.html | 2 +- releases/next/docs/signed-apk-android.html | 18 +- releases/next/docs/slider.html | 2 +- releases/next/docs/snapshotviewios.html | 2 +- releases/next/docs/state.html | 36 +-- releases/next/docs/statusbar.html | 20 +- releases/next/docs/statusbarios.html | 2 +- releases/next/docs/style.html | 24 +- releases/next/docs/stylesheet.html | 14 +- releases/next/docs/switch.html | 2 +- releases/next/docs/systrace.html | 2 +- releases/next/docs/tabbarios-item.html | 2 +- releases/next/docs/tabbarios.html | 2 +- releases/next/docs/testing.html | 4 +- releases/next/docs/text.html | 124 ++++---- releases/next/docs/textinput.html | 52 +-- releases/next/docs/timepickerandroid.html | 8 +- releases/next/docs/timers.html | 14 +- releases/next/docs/toastandroid.html | 6 +- releases/next/docs/toolbarandroid.html | 10 +- releases/next/docs/touchablehighlight.html | 10 +- .../next/docs/touchablenativefeedback.html | 14 +- releases/next/docs/touchableopacity.html | 10 +- .../next/docs/touchablewithoutfeedback.html | 2 +- releases/next/docs/transforms.html | 2 +- releases/next/docs/troubleshooting.html | 10 +- releases/next/docs/tutorial.html | 14 +- releases/next/docs/understanding-cli.html | 4 +- releases/next/docs/upgrading.html | 16 +- releases/next/docs/using-a-listview.html | 26 +- releases/next/docs/using-a-scrollview.html | 80 ++--- releases/next/docs/vibration.html | 2 +- releases/next/docs/vibrationios.html | 2 +- releases/next/docs/view.html | 16 +- releases/next/docs/viewpagerandroid.html | 22 +- releases/next/docs/virtualizedlist.html | 2 +- releases/next/docs/webview.html | 14 +- releases/next/img/PerfUtil.png | Bin 0 -> 23197 bytes releases/next/index.html | 62 ++-- releases/next/js/scripts.js | 186 ++++++++++- releases/next/versions.html | 2 +- showcase.html | 2 +- support.html | 2 +- versions.html | 4 +- 142 files changed, 2150 insertions(+), 2036 deletions(-) create mode 100644 releases/next/css/prism.css create mode 100644 releases/next/img/PerfUtil.png diff --git a/blog/2016/03/24/introducing-hot-reloading.html b/blog/2016/03/24/introducing-hot-reloading.html index ca9522b349b..5d48185c957 100644 --- a/blog/2016/03/24/introducing-hot-reloading.html +++ b/blog/2016/03/24/introducing-hot-reloading.html @@ -1,38 +1,38 @@ -Introducing Hot Reloading
React Native Blog
Stay up-to-date with the latest React Native news and events.

Introducing Hot Reloading

React Native's goal is to give you the best possible developer experience. A big part of it is the time it takes between you save a file and be able to see the changes. Our goal is to get this feedback loop to be under 1 second, even as your app grows.

We got close to this ideal via three main features:

  • Use JavaScript as the language doesn't have a long compilation cycle time.
  • Implement a tool called Packager that transforms es6/flow/jsx files into normal JavaScript that the VM can understand. It was designed as a server that keeps intermediate state in memory to enable fast incremental changes and uses multiple cores.
  • Build a feature called Live Reload that reloads the app on save.

At this point, the bottleneck for developers is no longer the time it takes to reload the app but losing the state of your app. A common scenario is to work on a feature that is multiple screens away from the launch screen. Every time you reload, you've got to click on the same path again and again to get back to your feature, making the cycle multiple-seconds long.

Hot Reloading #

The idea behind hot reloading is to keep the app running and to inject new versions of the files that you edited at runtime. This way, you don't lose any of your state which is especially useful if you are tweaking the UI.

A video is worth a thousand words. Check out the difference between Live Reload (current) and Hot Reload (new).

+Introducing Hot Reloading
React Native Blog
Stay up-to-date with the latest React Native news and events.

Introducing Hot Reloading

React Native's goal is to give you the best possible developer experience. A big part of it is the time it takes between you save a file and be able to see the changes. Our goal is to get this feedback loop to be under 1 second, even as your app grows.

We got close to this ideal via three main features:

  • Use JavaScript as the language doesn't have a long compilation cycle time.
  • Implement a tool called Packager that transforms es6/flow/jsx files into normal JavaScript that the VM can understand. It was designed as a server that keeps intermediate state in memory to enable fast incremental changes and uses multiple cores.
  • Build a feature called Live Reload that reloads the app on save.

At this point, the bottleneck for developers is no longer the time it takes to reload the app but losing the state of your app. A common scenario is to work on a feature that is multiple screens away from the launch screen. Every time you reload, you've got to click on the same path again and again to get back to your feature, making the cycle multiple-seconds long.

Hot Reloading #

The idea behind hot reloading is to keep the app running and to inject new versions of the files that you edited at runtime. This way, you don't lose any of your state which is especially useful if you are tweaking the UI.

A video is worth a thousand words. Check out the difference between Live Reload (current) and Hot Reload (new).

If you look closely, you can notice that it is possible to recover from a red box and you can also start importing modules that were not previously there without having to do a full reload.

Word of warning: because JavaScript is a very stateful language, hot reloading cannot be perfectly implemented. In practice, we found out that the current setup is working well for a large amount of usual use cases and a full reload is always available in case something gets messed up.

Hot reloading is available as of 0.22, you can enable it:

  • Open the developer menu
  • Tap on "Enable Hot Reloading"

Implementation in a nutshell #

Now that we've seen why we want it and how to use it, the fun part begins: how it actually works.

Hot Reloading is built on top of a feature Hot Module Replacement, or HMR. It was first introduced by Webpack and we implemented it inside of React Native Packager. HMR makes the Packager watch for file changes and send HMR updates to a thin HMR runtime included on the app.

In a nutshell, the HMR update contains the new code of the JS modules that changed. When the runtime receives them, it replaces the old modules' code with the new one:

The HMR update contains a bit more than just the module's code we want to change because replacing it, it's not enough for the runtime to pick up the changes. The problem is that the module system may have already cached the exports of the module we want to update. For instance, say you have an app composed of these two modules:

// log.js -function log(message) { - const time = require('./time'); - console.log(`[${time()}] ${message}`); +function log(message) { + const time = require('./time'); + console.log(`[${time()}] ${message}`); } module.exports = log;
// time.js -function time() { - return new Date().getTime(); +function time() { + return new Date().getTime(); } -module.exports = time;

The module log, prints out the provided message including the current date provided by the module time.

When the app is bundled, React Native registers each module on the module system using the __d function. For this app, among many __d definitions, there will one for log:

__d('log', function() { - ... // module's code +module.exports = time;

The module log, prints out the provided message including the current date provided by the module time.

When the app is bundled, React Native registers each module on the module system using the __d function. For this app, among many __d definitions, there will one for log:

__d('log', function() { + ... // module's code });

This invocation wraps each module's code into an anonymous function which we generally refer to as the factory function. The module system runtime keeps track of each module's factory function, whether it has already been executed, and the result of such execution (exports). When a module is required, the module system either provides the already cached exports or executes the module's factory function for the first time and saves the result.

So say you start your app and require log. At this point, neither log nor time's factory functions have been executed so no exports have been cached. Then, the user modifies time to return the date in MM/DD:

// time.js -function bar() { +function bar() { var date = new Date(); - return `${date.getMonth() + 1}/${date.getDate()}`; + return `${date.getMonth() + 1}/${date.getDate()}`; } -module.exports = bar;

The Packager will send time's new code to the runtime (step 1), and when log gets eventually required the exported function gets executed it will do so with time's changes (step 2):

Now say the code of log requires time as a top level require:

const time = require('./time'); // top level require +module.exports = bar;

The Packager will send time's new code to the runtime (step 1), and when log gets eventually required the exported function gets executed it will do so with time's changes (step 2):

Now say the code of log requires time as a top level require:

const time = require('./time'); // top level require // log.js -function log(message) { - console.log(`[${time()}] ${message}`); +function log(message) { + console.log(`[${time()}] ${message}`); } module.exports = log;

When log is required, the runtime will cache its exports and time's one. (step 1). Then, when time is modified, the HMR process cannot simply finish after replacing time's code. If it did, when log gets executed, it would do so with a cached copy of time (old code).

For log to pick up time changes, we'll need to clear its cached exports because one of the modules it depends on was hot swapped (step 3). Finally, when log gets required again, its factory function will get executed requiring time and getting its new code.

HMR API #

HMR in React Native extends the module system by introducing the hot object. This API is based on Webpack's one. The hot object exposes a function called accept which allows you to define a callback that will be executed when the module needs to be hot swapped. For instance, if we would change time's code as follows, every time we save time, we'll see “time changed” in the console:

// time.js -function time() { - ... // new code +function time() { + ... // new code } -module.hot.accept(() => { - console.log('time changed'); +module.hot.accept(() => { + console.log('time changed'); }); module.exports = time;

Note that only in rare cases you would need to use this API manually. Hot Reloading should work out of the box for the most common use cases.

HMR Runtime #

As we've seen before, sometimes it's not enough only accepting the HMR update because a module that uses the one being hot swapped may have been already executed and its imports cached. For instance, suppose the dependency tree for the movies app example had a top-level MovieRouter that depended on the MovieSearch and MovieScreen views, which depended on the log and time modules from the previous examples:

If the user accesses the movies' search view but not the other one, all the modules except for MovieScreen would have cached exports. If a change is made to module time, the runtime will have to clear the exports of log for it to pick up time's changes. The process wouldn't finish there: the runtime will repeat this process recursively up until all the parents have been accepted. So, it'll grab the modules that depend on log and try to accept them. For MovieScreen it can bail, as it hasn't been required yet. For MovieSearch, it will have to clear its exports and process its parents recursively. Finally, it will do the same thing for MovieRouter and finish there as no modules depends on it.

In order to walk the dependency tree, the runtime receives the inverse dependency tree from the Packager on the HMR update. For this example the runtime will receive a JSON object like this one:

{ @@ -50,21 +50,21 @@ module.exports : ['log'], } }

React Components #

React components are a bit harder to get to work with Hot Reloading. The problem is that we can't simply replace the old code with the new one as we'd loose the component's state. For React web applications, Dan Abramov implemented a babel transform that uses Webpack's HMR API to solve this issue. In a nutshell, his solution works by creating a proxy for every single React component on transform time. The proxies hold the component's state and delegate the lifecycle methods to the actual components, which are the ones we hot reload:

Besides creating the proxy component, the transform also defines the accept function with a piece of code to force React to re-render the component. This way, we can hot reload rendering code without losing any of the app's state.

The default transformer that comes with React Native uses the babel-preset-react-native, which is configured to use react-transform the same way you'd use it on a React web project that uses Webpack.

Redux Stores #

To enable Hot Reloading on Redux stores you will just need to use the HMR API similarly to what you'd do on a web project that uses Webpack:

// configureStore.js -import { createStore, applyMiddleware, compose } from 'redux'; -import thunk from 'redux-thunk'; -import reducer from '../reducers'; +import { createStore, applyMiddleware, compose } from 'redux'; +import thunk from 'redux-thunk'; +import reducer from '../reducers'; -export default function configureStore(initialState) { - const store = createStore( +export default function configureStore(initialState) { + const store = createStore( reducer, initialState, - applyMiddleware(thunk), + applyMiddleware(thunk), ); if (module.hot) { - module.hot.accept(() => { - const nextRootReducer = require('../reducers/index').default; - store.replaceReducer(nextRootReducer); + module.hot.accept(() => { + const nextRootReducer = require('../reducers/index').default; + store.replaceReducer(nextRootReducer); }); } diff --git a/blog/2016/07/06/toward-better-documentation.html b/blog/2016/07/06/toward-better-documentation.html index 53a363ffa17..24733623696 100644 --- a/blog/2016/07/06/toward-better-documentation.html +++ b/blog/2016/07/06/toward-better-documentation.html @@ -1,22 +1,22 @@ -Toward Better Documentation
React Native Blog
Stay up-to-date with the latest React Native news and events.

Toward Better Documentation

Part of having a great developer experience is having great documentation. A lot goes into creating good docs - the ideal documentation is concise, helpful, accurate, complete, and delightful. Recently we've been working hard to make the docs better based on your feedback, and we wanted to share some of the improvements we've made.

Inline Examples #

When you learn a new library, a new programming language, or a new framework, there's a beautiful moment when you first write a bit of code, try it out, see if it works... and it does work. You created something real. We wanted to put that visceral experience right into our docs. Like this:

import React, { Component } from 'react'; -import { AppRegistry, Text, View } from 'react-native'; +Toward Better Documentation
React Native Blog
Stay up-to-date with the latest React Native news and events.

Toward Better Documentation

Part of having a great developer experience is having great documentation. A lot goes into creating good docs - the ideal documentation is concise, helpful, accurate, complete, and delightful. Recently we've been working hard to make the docs better based on your feedback, and we wanted to share some of the improvements we've made.

Inline Examples #

When you learn a new library, a new programming language, or a new framework, there's a beautiful moment when you first write a bit of code, try it out, see if it works... and it does work. You created something real. We wanted to put that visceral experience right into our docs. Like this:

import React, { Component } from 'react'; +import { AppRegistry, Text, View } from 'react-native'; -class ScratchPad extends Component { - render() { +class ScratchPad extends Component { + render() { return ( - <View style={{flex: 1}}> - <Text style={{fontSize: 30, flex: 1, textAlign: 'center'}}> + <View style={{flex: 1}}> + <Text style={{fontSize: 30, flex: 1, textAlign: 'center'}}> Isn't this cool? - </Text> - <Text style={{fontSize: 100, flex: 1, textAlign: 'center'}}> + </Text> + <Text style={{fontSize: 100, flex: 1, textAlign: 'center'}}> 👍 - </Text> - </View> + </Text> + </View> ); } } -AppRegistry.registerComponent('ScratchPad', () => ScratchPad);

We think these inline examples, using the react-native-web-player module with help from Devin Abbott, are a great way to learn the basics of React Native, and we have updated our tutorial for new React Native developers to use these wherever possible. Check it out - if you have ever been curious to see what would happen if you modified just one little bit of sample code, this is a really nice way to poke around. Also, if you're building developer tools and you want to show a live React Native sample on your own site, react-native-web-player can make that straightforward.

The core simulation engine is provided by Nicolas Gallagher's react-native-web project, which provides a way to display React Native components like Text and View on the web. Check out react-native-web if you're interested in building mobile and web experiences that share a large chunk of the codebase.

Better Guides #

In some parts of React Native, there are multiple ways to do things, and we've heard feedback that we could provide better guidance.

We have a new guide to Navigation that compares the different approaches and advises on what you should use - Navigator, NavigatorIOS, NavigationExperimental. In the medium term, we're working towards improving and consolidating those interfaces. In the short term, we hope that a better guide will make your life easier.

We also have a new guide to handling touches that explains some of the basics of making button-like interfaces, and a brief summary of the different ways to handle touch events.

Another area we worked on is Flexbox. This includes tutorials on how to handle layout with Flexbox and how to control the size of components. It also includes an unsexy but hopefully-useful list of all the props that control layout in React Native.

Getting Started #

When you start getting a React Native development environment set up on your machine, you do have to do a bunch of installing and configuring things. It's hard to make installation a really fun and exciting experience, but we can at least make it as quick and painless as possible.

We built a new Getting Started workflow that lets you select your development operating system and your mobile operating system up front, to provide one concise place with all the setup instructions. We also went through the installation process to make sure everything worked and to make sure that every decision point had a clear recommendation. After testing it out on our innocent coworkers, we're pretty sure this is an improvement.

We also worked on the guide to integrating React Native into an existing app. Many of the largest apps that use React Native, like the Facebook app itself, actually build part of the app in React Native, and part of it using regular development tools. We hope this guide makes it easier for more people to build apps this way.

We Need Your Help #

Your feedback lets us know what we should prioritize. I know some people will read this blog post and think "Better docs? Pffft. The documentation for X is still garbage!". That's great - we need that energy. The best way to give us feedback depends on the sort of feedback.

If you find a mistake in the documentation, like inaccurate descriptions or code that doesn't actually work, file an issue. Tag it with "Documentation", so that it's easier to route it to the right people.

If there isn't a specific mistake, but something in the documentation is fundamentally confusing, it's not a great fit for a GitHub issue. Instead, post on Canny about the area of the docs that could use help. This helps us prioritize when we are doing more general work like guide-writing.

Thanks for reading this far, and thanks for using React Native!

React Native Blog
Stay up-to-date with the latest React Native news and events.

San Francisco Meetup Recap

Last week I had the opportunity to attend the React Native Meetup at Zynga’s San Francisco office. With around 200 people in attendance, it served as a great place to meet other developers near me that are also interested in React Native.

I was particularly interested in learning more about how React and React Native are used at companies like Zynga, Netflix, and Airbnb. The agenda for the night would be as follows:

  • Rapid Prototyping in React
  • Designing APIs for React Native
  • Bridging the Gap: Using React Native in Existing Codebases

But first, the event started off with a quick introduction and a brief recap of recent news:

If one of these meetups is held near you, I highly recommend attending!

Rapid Prototyping in React at Zynga #

The first round of news was followed by a quick introduction by Zynga, our hosts for the evening. Abhishek Chadha talked about how they use React to quickly prototype new experiences on mobile, demoing a quick prototype of a Draw Something-like app. They use a similar approach as React Native, providing access to native APIs via a bridge. This was demonstrated when Abhishek used the device's camera to snap a photo of the audience and then drew a hat on someone's head.

Designing APIs for React Native at Netflix #

Up next, the first featured talk of the evening. Clarence Leung, Senior Software Engineer at Netflix, presented his talk on Designing APIs for React Native. First he noted the two main types of libraries one may work on: components such as tab bars and date pickers, and libraries that provide access to native services such as the camera roll or in-app payments. There are two ways one may approach when building a library for use in React Native:

  • Provide platform-specific components
  • A cross-platform library with a similar API for both iOS and Android

Each approach has its own considerations, and it’s up to you to determine what works best for your needs.

Approach #1

As an example of platform-specific components, Clarence talked about the DatePickerIOS and DatePickerAndroid from core React Native. On iOS, date pickers are rendered as part of the UI and can be easily embedded in an existing view, while date pickers on Android are presented modally. It makes sense to provide separate components in this case.

Approach #2

Photo pickers, on the other hand, are treated similarly on iOS and Android. There are some slight differences — Android does not group photos into folders like iOS does with Selfies, for example — but those are easily handled using if statements and the Platform component.

Regardless of which approach you settle on, it’s a good idea to minimize the API surface and build app-specific libraries. For example, iOS’s In-App Purchase framework supports one-time, consumable purchases, as well as renewable subscriptions. If your app will only need to support consumable purchases, you may get away with dropping support for subscriptions in your cross-platform library.

There was a brief Q&A session at the end of Clarence’s talk. One of the interesting tid bits that came out of it was that around 80% of the React Native code written for these libraries at Netflix is shared across both iOS and Android.

Bridging the Gap, Using React Native in Existing Codebases #

The final talk of the night was by Leland Richardson from Airbnb. The talk was focused on the use of React Native in existing codebases. I already know how easy it is to write a new app from scratch using React Native, so I was very interested to hear about Airbnb’s experience adopting React Native in their existing native apps.

Leland started off by talking about greenfield apps versus brownfield apps. Greenfield means to start a project without the need to consider any prior work. This is in contrast to brownfield projects where you need to take into account the existing project’s requirements, development processes, and all of the teams various needs.

When you’re working on a greenfield app, the React Native CLI sets up a single repository for both iOS and Android and everything just works. The first challenge against using React Native at Airbnb was the fact that the iOS and Android app each had their own repository. Multi-repo companies have some hurdles to get past before they can adopt React Native.

To get around this, Airbnb first set up a new repo for the React Native codebase. They used their continuous integration servers to mirror the iOS and Android repos into this new repo. After tests are run and the bundle is built, the build artifacts are synced back to the iOS and Android repos. This allows the mobile engineers to work on native code without altering their development enviroment. Mobile engineers don't need to install npm, run the packager, or remember to build the JavaScript bundle. The engineers writing actual React Native code do not have to worry about syncing their code across iOS and Android, as they work on the React Native repository directly.

This does come with some drawbacks, mainly they could not ship atomic updates. Changes that require a combination of native and JavaScript code would require three separate pull requests, all of which had to be carefully landed. In order to avoid conflicts, CI will fail to land changes back to the iOS and Android repos if master has changed since the build started. This would cause long delays during high commit frequency days (such as when new releases are cut).

Airbnb has since moved to a mono repo approach. Fortunately this was already under consideration, and once the iOS and Android teams became comfortable with using React Native they were happy to accelerate the move towards the mono repo.

This has solved most of the issues they had with the split repo approach. Leland did note that this does cause a higher strain on the version control servers, which may be an issue for smaller companies.

The Navigation Problem #

The second half of Leland's talk focused on a topic that is dear to me: the Navigation problem in React Native. He talked about the abundance of navigation libraries in React Native, both first party and third party. NavigationExperimental was mentioned as something that seemed promising, but ended up not being well suited for their use case.

In fact, none of the existing navigation libraries seem to work well for brownfield apps. A brownfield app requires that the navigation state be fully owned by the native app. For example, if a user’s session expires while a React Native view is being presented, the native app should be able to take over and present a login screen as needed.

Airbnb also wanted to avoid replacing native navigation bars with JavaScript versions as part of a transition, as the effect could be jarring. Initially they limited themselves to modally presented views, but this obviously presented a problem when it came to adopting React Native more widely within their apps.

They decided that they needed their own library. The library is called airbnb-navigation. The library has not yet being open sourced as it is strongly tied to Airbnb’s codebase, but it is something they’d like to release by the end of the year.

I won’t go into much detail into the library’s API, but here are some of the key takeaways:

  • One must preregister scenes ahead of time
  • Each scene is displayed within its own RCTRootView. They are presented natively on each platform (e.g. UINavigationControllers are used on iOS).
  • The main ScrollView in a scene should be wrapped in a ScrollScene component. Doing so allows you to take advantage of native behaviors such as tapping on the status bar to scroll to the top on iOS.
  • Transitions between scenes are handled natively, no need to worry about performance.
  • The Android back button is automatically supported.
  • They can take advantage of View Controller based navigation bar styling via a Navigator.Config UI-less component.

There’s also some considerations to keep in mind:

  • The navigation bar is not easily customized in JavaScript, as it is a native component. This is intentional, as using native navigation bars is a hard requirement for this type of library.
  • ScreenProps must be serialized/de-serialized whenever they're sent through the bridge, so care must be taken if sending too much data here.
  • Navigation state is owned by the native app (also a hard requirement for the library), so things like Redux cannot manipulate navigation state.

Leland's talk was also followed by a Q&A session. Overall, Airbnb is satisfied with React Native. They’re interested in using Code Push to fix any issues without going through the App Store, and their engineers love Live Reload, as they don't have to wait for the native app to be rebuilt after every minor change.

Closing Remarks #

The event ended with some additional React Native news:

Meetups provide a good opportunity to meet and learn from other developers in the community. I'm looking forward to attending more React Native meetups in the future. If you make it up to one of these, please look out for me and let me know how we can make React Native work better for you!

React Native Blog
Stay up-to-date with the latest React Native news and events.

San Francisco Meetup Recap

Last week I had the opportunity to attend the React Native Meetup at Zynga’s San Francisco office. With around 200 people in attendance, it served as a great place to meet other developers near me that are also interested in React Native.

I was particularly interested in learning more about how React and React Native are used at companies like Zynga, Netflix, and Airbnb. The agenda for the night would be as follows:

  • Rapid Prototyping in React
  • Designing APIs for React Native
  • Bridging the Gap: Using React Native in Existing Codebases

But first, the event started off with a quick introduction and a brief recap of recent news:

If one of these meetups is held near you, I highly recommend attending!

Rapid Prototyping in React at Zynga #

The first round of news was followed by a quick introduction by Zynga, our hosts for the evening. Abhishek Chadha talked about how they use React to quickly prototype new experiences on mobile, demoing a quick prototype of a Draw Something-like app. They use a similar approach as React Native, providing access to native APIs via a bridge. This was demonstrated when Abhishek used the device's camera to snap a photo of the audience and then drew a hat on someone's head.

Designing APIs for React Native at Netflix #

Up next, the first featured talk of the evening. Clarence Leung, Senior Software Engineer at Netflix, presented his talk on Designing APIs for React Native. First he noted the two main types of libraries one may work on: components such as tab bars and date pickers, and libraries that provide access to native services such as the camera roll or in-app payments. There are two ways one may approach when building a library for use in React Native:

  • Provide platform-specific components
  • A cross-platform library with a similar API for both iOS and Android

Each approach has its own considerations, and it’s up to you to determine what works best for your needs.

Approach #1

As an example of platform-specific components, Clarence talked about the DatePickerIOS and DatePickerAndroid from core React Native. On iOS, date pickers are rendered as part of the UI and can be easily embedded in an existing view, while date pickers on Android are presented modally. It makes sense to provide separate components in this case.

Approach #2

Photo pickers, on the other hand, are treated similarly on iOS and Android. There are some slight differences — Android does not group photos into folders like iOS does with Selfies, for example — but those are easily handled using if statements and the Platform component.

Regardless of which approach you settle on, it’s a good idea to minimize the API surface and build app-specific libraries. For example, iOS’s In-App Purchase framework supports one-time, consumable purchases, as well as renewable subscriptions. If your app will only need to support consumable purchases, you may get away with dropping support for subscriptions in your cross-platform library.

There was a brief Q&A session at the end of Clarence’s talk. One of the interesting tid bits that came out of it was that around 80% of the React Native code written for these libraries at Netflix is shared across both iOS and Android.

Bridging the Gap, Using React Native in Existing Codebases #

The final talk of the night was by Leland Richardson from Airbnb. The talk was focused on the use of React Native in existing codebases. I already know how easy it is to write a new app from scratch using React Native, so I was very interested to hear about Airbnb’s experience adopting React Native in their existing native apps.

Leland started off by talking about greenfield apps versus brownfield apps. Greenfield means to start a project without the need to consider any prior work. This is in contrast to brownfield projects where you need to take into account the existing project’s requirements, development processes, and all of the teams various needs.

When you’re working on a greenfield app, the React Native CLI sets up a single repository for both iOS and Android and everything just works. The first challenge against using React Native at Airbnb was the fact that the iOS and Android app each had their own repository. Multi-repo companies have some hurdles to get past before they can adopt React Native.

To get around this, Airbnb first set up a new repo for the React Native codebase. They used their continuous integration servers to mirror the iOS and Android repos into this new repo. After tests are run and the bundle is built, the build artifacts are synced back to the iOS and Android repos. This allows the mobile engineers to work on native code without altering their development enviroment. Mobile engineers don't need to install npm, run the packager, or remember to build the JavaScript bundle. The engineers writing actual React Native code do not have to worry about syncing their code across iOS and Android, as they work on the React Native repository directly.

This does come with some drawbacks, mainly they could not ship atomic updates. Changes that require a combination of native and JavaScript code would require three separate pull requests, all of which had to be carefully landed. In order to avoid conflicts, CI will fail to land changes back to the iOS and Android repos if master has changed since the build started. This would cause long delays during high commit frequency days (such as when new releases are cut).

Airbnb has since moved to a mono repo approach. Fortunately this was already under consideration, and once the iOS and Android teams became comfortable with using React Native they were happy to accelerate the move towards the mono repo.

This has solved most of the issues they had with the split repo approach. Leland did note that this does cause a higher strain on the version control servers, which may be an issue for smaller companies.

The Navigation Problem #

The second half of Leland's talk focused on a topic that is dear to me: the Navigation problem in React Native. He talked about the abundance of navigation libraries in React Native, both first party and third party. NavigationExperimental was mentioned as something that seemed promising, but ended up not being well suited for their use case.

In fact, none of the existing navigation libraries seem to work well for brownfield apps. A brownfield app requires that the navigation state be fully owned by the native app. For example, if a user’s session expires while a React Native view is being presented, the native app should be able to take over and present a login screen as needed.

Airbnb also wanted to avoid replacing native navigation bars with JavaScript versions as part of a transition, as the effect could be jarring. Initially they limited themselves to modally presented views, but this obviously presented a problem when it came to adopting React Native more widely within their apps.

They decided that they needed their own library. The library is called airbnb-navigation. The library has not yet being open sourced as it is strongly tied to Airbnb’s codebase, but it is something they’d like to release by the end of the year.

I won’t go into much detail into the library’s API, but here are some of the key takeaways:

  • One must preregister scenes ahead of time
  • Each scene is displayed within its own RCTRootView. They are presented natively on each platform (e.g. UINavigationControllers are used on iOS).
  • The main ScrollView in a scene should be wrapped in a ScrollScene component. Doing so allows you to take advantage of native behaviors such as tapping on the status bar to scroll to the top on iOS.
  • Transitions between scenes are handled natively, no need to worry about performance.
  • The Android back button is automatically supported.
  • They can take advantage of View Controller based navigation bar styling via a Navigator.Config UI-less component.

There’s also some considerations to keep in mind:

  • The navigation bar is not easily customized in JavaScript, as it is a native component. This is intentional, as using native navigation bars is a hard requirement for this type of library.
  • ScreenProps must be serialized/de-serialized whenever they're sent through the bridge, so care must be taken if sending too much data here.
  • Navigation state is owned by the native app (also a hard requirement for the library), so things like Redux cannot manipulate navigation state.

Leland's talk was also followed by a Q&A session. Overall, Airbnb is satisfied with React Native. They’re interested in using Code Push to fix any issues without going through the App Store, and their engineers love Live Reload, as they don't have to wait for the native app to be rebuilt after every minor change.

Closing Remarks #

The event ended with some additional React Native news:

Meetups provide a good opportunity to meet and learn from other developers in the community. I'm looking forward to attending more React Native meetups in the future. If you make it up to one of these, please look out for me and let me know how we can make React Native work better for you!

React Native Blog
Stay up-to-date with the latest React Native news and events.

Right-to-Left Layout Support For React Native Apps

After launching an app to the app stores, internationalization is the next step to further your audience reach. Over 20 countries and numerous people around the world use Right-to-Left (RTL) languages. Thus, making your app support RTL for them is necessary.

We're glad to announce that React Native has been improved to support RTL layouts. This is now available in the react-native master branch today, and will be available in the next RC: v0.33.0-rc.

This involved changing css-layout, the core layout engine used by RN, and RN core implementation, as well as specific OSS JS components to support RTL.

To battle test the RTL support in production, the latest version of the Facebook Ads Manager app (the first cross-platform 100% RN app) is now available in Arabic and Hebrew with RTL layouts for both iOS and Android. Here is how it looks like in those RTL languages:

+Right-to-Left Layout Support For React Native Apps

React Native Blog
Stay up-to-date with the latest React Native news and events.

Right-to-Left Layout Support For React Native Apps

After launching an app to the app stores, internationalization is the next step to further your audience reach. Over 20 countries and numerous people around the world use Right-to-Left (RTL) languages. Thus, making your app support RTL for them is necessary.

We're glad to announce that React Native has been improved to support RTL layouts. This is now available in the react-native master branch today, and will be available in the next RC: v0.33.0-rc.

This involved changing css-layout, the core layout engine used by RN, and RN core implementation, as well as specific OSS JS components to support RTL.

To battle test the RTL support in production, the latest version of the Facebook Ads Manager app (the first cross-platform 100% RN app) is now available in Arabic and Hebrew with RTL layouts for both iOS and Android. Here is how it looks like in those RTL languages:

-

Overview Changes in RN for RTL support #

css-layout already has a concept of start and end for the layout. In the Left-to-Right (LTR) layout, start means left, and end means right. But in RTL, start means right, and end means left. This means we can make RN depend on the start and end calculation to compute the correct layout, which includes position, padding, and margin.

In addition, css-layout already makes each component's direction inherits from its parent. This means, we simply need to set the direction of the root component to RTL, and the entire app will flip.

The diagram below describes the changes at high level:

These include:

With this update, when you allow RTL layout for your app:

  • every component layout will flip horizontally
  • some gestures and animations will automatically have RTL layout, if you are using RTL-ready OSS components
  • minimal additional effort may be needed to make your app fully RTL-ready

Making an App RTL-ready #

  1. To support RTL, you should first add the RTL language bundles to your app.

  2. Allow RTL layout for your app by calling the allowRTL() function at the beginning of native code. We provided this utility to only apply to an RTL layout when your app is ready. Here is an example:

    iOS:

    // in AppDelegate.m - [[RCTI18nUtil sharedInstance] allowRTL:YES];

    Android:

    // in MainActivity.java +

    Overview Changes in RN for RTL support #

    css-layout already has a concept of start and end for the layout. In the Left-to-Right (LTR) layout, start means left, and end means right. But in RTL, start means right, and end means left. This means we can make RN depend on the start and end calculation to compute the correct layout, which includes position, padding, and margin.

    In addition, css-layout already makes each component's direction inherits from its parent. This means, we simply need to set the direction of the root component to RTL, and the entire app will flip.

    The diagram below describes the changes at high level:

    These include:

    With this update, when you allow RTL layout for your app:

    • every component layout will flip horizontally
    • some gestures and animations will automatically have RTL layout, if you are using RTL-ready OSS components
    • minimal additional effort may be needed to make your app fully RTL-ready

    Making an App RTL-ready #

    1. To support RTL, you should first add the RTL language bundles to your app.

    2. Allow RTL layout for your app by calling the allowRTL() function at the beginning of native code. We provided this utility to only apply to an RTL layout when your app is ready. Here is an example:

      iOS:

      // in AppDelegate.m + [[RCTI18nUtil sharedInstance] allowRTL:YES];

      Android:

      // in MainActivity.java I18nUtil sharedI18nUtilInstance = I18nUtil.getInstance(); sharedI18nUtilInstance.setAllowRTL(context, true);
    3. For Android, you need add android:supportsRtl="true" to the <application> element in AndroidManifest.xml file.

    Now, when you recompile your app and change the device language to an RTL language (e.g. Arabic or Hebrew), your app layout should change to RTL automatically.

    Writing RTL-ready Components #

    In general, most components are already RTL-ready, for example:

    • Left-to-Right Layout

      @@ -20,36 +20,36 @@

      -

    Here are two ways to flip the icon according to the direction:

    • Adding a transform style to the image component:

      <Image - source={...} +

    Here are two ways to flip the icon according to the direction:

    • Adding a transform style to the image component:

      <Image + source={...} style={{transform: [{scaleX: I18nManager.isRTL ? -1 : 1}]}} -/>
    • Or, changing the image source according to the direction:

      let imageSource = require('./back.png'); +/>
    • Or, changing the image source according to the direction:

      let imageSource = require('./back.png'); if (I18nManager.isRTL) { - imageSource = require('./forward.png'); + imageSource = require('./forward.png'); } return ( - <Image source={imageSource} /> + <Image source={imageSource} /> );

    Gestures and Animations #

    In iOS and Android development, when you change to RTL layout, the gestures and animations are the opposite of LTR layout. Currently, in RN, gestures and animations are not supported on RN core code level, but on components level. The good news is, some of these components already support RTL today, such as SwipeableRow and NavigationExperimental. However, other components with gestures will need to support RTL manually.

    A good example to illustrate gesture RTL support is SwipeableRow.

    -
    Gestures Example #
    // SwipeableRow.js -_isSwipingExcessivelyRightFromClosedPosition(gestureState: Object): boolean { +
    Gestures Example #
    // SwipeableRow.js +_isSwipingExcessivelyRightFromClosedPosition(gestureState: Object): boolean { // ... - const gestureStateDx = IS_RTL ? -gestureState.dx : gestureState.dx; + const gestureStateDx = IS_RTL ? -gestureState.dx : gestureState.dx; return ( - this._isSwipingRightFromClosed(gestureState) && + this._isSwipingRightFromClosed(gestureState) && gestureStateDx > RIGHT_SWIPE_THRESHOLD ); -},
    Animation Example #
    // SwipeableRow.js -_animateBounceBack(duration: number): void { +},
    Animation Example #
    // SwipeableRow.js +_animateBounceBack(duration: number): void { // ... - const swipeBounceBackDistance = IS_RTL ? + const swipeBounceBackDistance = IS_RTL ? -RIGHT_SWIPE_BOUNCE_BACK_DISTANCE : RIGHT_SWIPE_BOUNCE_BACK_DISTANCE; - this._animateTo( + this._animateTo( -swipeBounceBackDistance, duration, this._animateToClosedPositionDuringBounce, @@ -58,24 +58,24 @@

    -
    <RNTesterBlock title={'Quickly Test RTL Layout'}> - <View style={styles.flexDirectionRow}> - <Text style={styles.switchRowTextView}> +
    <RNTesterBlock title={'Quickly Test RTL Layout'}> + <View style={styles.flexDirectionRow}> + <Text style={styles.switchRowTextView}> forceRTL - </Text> - <View style={styles.switchRowSwitchView}> - <Switch + </Text> + <View style={styles.switchRowSwitchView}> + <Switch onValueChange={this._onDirectionChange} style={styles.rightAlignStyle} value={this.state.isRTL} /> - </View> - </View> -</RNTesterBlock> + </View> + </View> +</RNTesterBlock> -_onDirectionChange = () => { - I18nManager.forceRTL(!this.state.isRTL); - this.setState({isRTL: !this.state.isRTL}); - Alert.alert('Reload this page', +_onDirectionChange = () => { + I18nManager.forceRTL(!this.state.isRTL); + this.setState({isRTL: !this.state.isRTL}); + Alert.alert('Reload this page', 'Please reload this page to change the UI direction! ' + 'All examples in this app will be affected. ' + 'Check them out to see what they look like in RTL layout.' diff --git a/blog/2016/09/08/exponent-talks-unraveling-navigation.html b/blog/2016/09/08/exponent-talks-unraveling-navigation.html index 9b819471933..6acc24a0cf7 100644 --- a/blog/2016/09/08/exponent-talks-unraveling-navigation.html +++ b/blog/2016/09/08/exponent-talks-unraveling-navigation.html @@ -1,4 +1,4 @@ -Expo Talks: Adam on Unraveling Navigation
    React Native Blog
    Stay up-to-date with the latest React Native news and events.
    React Native Blog
    Stay up-to-date with the latest React Native news and events.
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    0.36: Headless JS, the Keyboard API, & more

    Today we are releasing React Native 0.36. Read on to learn more about what's new.

    Headless JS #

    Headless JS is a way to run tasks in JavaScript while your app is in the background. It can be used, for example, to sync fresh data, handle push notifications, or play music. It is only available on Android, for now.

    To get started, define your async task in a dedicated file (e.g. SomeTaskName.js):

    module.exports = async (taskData) => { +0.36: Headless JS, the Keyboard API, & more
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    0.36: Headless JS, the Keyboard API, & more

    Today we are releasing React Native 0.36. Read on to learn more about what's new.

    Headless JS #

    Headless JS is a way to run tasks in JavaScript while your app is in the background. It can be used, for example, to sync fresh data, handle push notifications, or play music. It is only available on Android, for now.

    To get started, define your async task in a dedicated file (e.g. SomeTaskName.js):

    module.exports = async (taskData) => { // Perform your task here. -}

    Next, register your task in on AppRegistry:

    AppRegistry.registerHeadlessTask('SomeTaskName', () => require('SomeTaskName'));

    Using Headless JS does require some native Java code to be written in order to allow you to start up the service when needed. Take a look at our new Headless JS docs to learn more!

    The Keyboard API #

    Working with the on-screen keyboard is now easier with Keyboard. You can now listen for native keyboard events and react to them. For example, to dismiss the active keyboard, simply call Keyboard.dismiss():

    import { Keyboard } from 'react-native' +}

    Next, register your task in on AppRegistry:

    AppRegistry.registerHeadlessTask('SomeTaskName', () => require('SomeTaskName'));

    Using Headless JS does require some native Java code to be written in order to allow you to start up the service when needed. Take a look at our new Headless JS docs to learn more!

    The Keyboard API #

    Working with the on-screen keyboard is now easier with Keyboard. You can now listen for native keyboard events and react to them. For example, to dismiss the active keyboard, simply call Keyboard.dismiss():

    import { Keyboard } from 'react-native' // Hide that keyboard! -Keyboard.dismiss()

    Animated Division #

    Combining two animated values via addition, multiplication, and modulo are already supported by React Native. With version 0.36, combining two animated values via division is now possible. There are some cases where an animated value needs to invert another animated value for calculation. An example is inverting a scale (2x --> 0.5x):

    const a = Animated.Value(1); -const b = Animated.divide(1, a); +Keyboard.dismiss()

    Animated Division #

    Combining two animated values via addition, multiplication, and modulo are already supported by React Native. With version 0.36, combining two animated values via division is now possible. There are some cases where an animated value needs to invert another animated value for calculation. An example is inverting a scale (2x --> 0.5x):

    const a = Animated.Value(1); +const b = Animated.divide(1, a); -Animated.spring(a, { +Animated.spring(a, { toValue: 2, -}).start();

    b will then follow a's spring animation and produce the value of 1 / a.

    The basic usage is like this:

    <Animated.View style={{transform: [{scale: a}]}}> - <Animated.Image style={{transform: [{scale: b}]}} /> -<Animated.View>

    In this example, the inner image won't get stretched at all because the parent's scaling gets cancelled out. If you'd like to learn more, check out the Animations guide.

    Dark Status Bars #

    A new barStyle value has been added to StatusBar: dark-content. With this addition, you can now use barStyle on both iOS and Android. The behavior will now be the following:

    • default: Use the platform default (light on iOS, dark on Android).
    • light-content: Use a light status bar with black text and icons.
    • dark-content: Use a dark status bar with white text and icons.

    ...and more #

    The above is just a sample of what has changed in 0.36. Check out the release notes on GitHub to see the full list of new features, bug fixes, and breaking changes.

    You can upgrade to 0.36 by running the following commands in a terminal:

    $ npm install --save react-native@0.36 +}).start();

    b will then follow a's spring animation and produce the value of 1 / a.

    The basic usage is like this:

    <Animated.View style={{transform: [{scale: a}]}}> + <Animated.Image style={{transform: [{scale: b}]}} /> +<Animated.View>

    In this example, the inner image won't get stretched at all because the parent's scaling gets cancelled out. If you'd like to learn more, check out the Animations guide.

    Dark Status Bars #

    A new barStyle value has been added to StatusBar: dark-content. With this addition, you can now use barStyle on both iOS and Android. The behavior will now be the following:

    • default: Use the platform default (light on iOS, dark on Android).
    • light-content: Use a light status bar with black text and icons.
    • dark-content: Use a dark status bar with white text and icons.

    ...and more #

    The above is just a sample of what has changed in 0.36. Check out the release notes on GitHub to see the full list of new features, bug fixes, and breaking changes.

    You can upgrade to 0.36 by running the following commands in a terminal:

    $ npm install --save react-native@0.36 $ react-native upgrade
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Introducing Button, Faster Installs with Yarn, and a Public Roadmap

    We have heard from many people that there is so much work happening with React Native, it can be tough to keep track of what's going on. To help communicate what work is in progress, we are now publishing a roadmap for React Native. At a high level, this work can be broken down into three priorities:

    • Core Libraries. Adding more functionality to the most useful components and APIs.
    • Stability. Improve the underlying infrastructure to reduce bugs and improve code quality.
    • Developer Experience. Help React Native developers move faster

    If you have suggestions for features that you think would be valuable on the roadmap, check out Canny, where you can suggest new features and discuss existing proposals.

    What's new in React Native #

    Version 0.37 of React Native, released today, introduces a new core component to make it really easy to add a touchable Button to any app. We're also introducing support for the new Yarn package manager, which should speed up the whole process of updating your app's dependencies.

    Introducing Button #

    Today we're introducing a basic <Button /> component that looks great on every platform. This addresses one of the most common pieces of feedback we get: React Native is one of the only mobile development toolkits without a button ready to use out of the box.

    Simple Button on Android, iOS

    <Button +Introducing Button, Faster Installs with Yarn, and a Public Roadmap
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Introducing Button, Faster Installs with Yarn, and a Public Roadmap

    We have heard from many people that there is so much work happening with React Native, it can be tough to keep track of what's going on. To help communicate what work is in progress, we are now publishing a roadmap for React Native. At a high level, this work can be broken down into three priorities:

    • Core Libraries. Adding more functionality to the most useful components and APIs.
    • Stability. Improve the underlying infrastructure to reduce bugs and improve code quality.
    • Developer Experience. Help React Native developers move faster

    If you have suggestions for features that you think would be valuable on the roadmap, check out Canny, where you can suggest new features and discuss existing proposals.

    What's new in React Native #

    Version 0.37 of React Native, released today, introduces a new core component to make it really easy to add a touchable Button to any app. We're also introducing support for the new Yarn package manager, which should speed up the whole process of updating your app's dependencies.

    Introducing Button #

    Today we're introducing a basic <Button /> component that looks great on every platform. This addresses one of the most common pieces of feedback we get: React Native is one of the only mobile development toolkits without a button ready to use out of the box.

    Simple Button on Android, iOS

    <Button onPress={onPressMe} title="Press Me" accessibilityLabel="Learn more about this Simple Button" diff --git a/blog/2016/12/05/easier-upgrades.html b/blog/2016/12/05/easier-upgrades.html index f851704f427..4183518e858 100644 --- a/blog/2016/12/05/easier-upgrades.html +++ b/blog/2016/12/05/easier-upgrades.html @@ -1,24 +1,24 @@ -Easier Upgrades Thanks to Git
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Easier Upgrades Thanks to Git

    Upgrading to new versions of React Native has been difficult. You might have seen something like this before:

    None of those options is ideal. By overwriting the file we lose our local changes. By not overwriting we don't get the latest updates.

    Today I am proud to introduce a new tool that helps solve this problem. The tool is called react-native-git-upgrade and uses Git behind the scenes to resolve conflicts automatically whenever possible.

    Usage #

    Requirement: Git has to be available in the PATH. Your project doesn't have to be managed by Git.

    Install react-native-git-upgrade globally:

    $ npm install -g react-native-git-upgrade

    or, using Yarn:

    $ yarn global add react-native-git-upgrade

    Then, run it inside your project directory:

    $ cd MyProject -$ react-native-git-upgrade 0.38.0

    Note: Do not run 'npm install' to install a new version of react-native. The tool needs to be able to compare the old and new project template to work correctly. Simply run it inside your app folder as shown above, while still on the old version.

    Example output:

    You can also run react-native-git-upgrade with no arguments to upgrade to the latest version of React Native.

    We try to preserve your changes in iOS and Android build files, so you don't need to run react-native link after an upgrade.

    We have designed the implementation to be as little intrusive as possible. It is entirely based on a local Git repository created on-the-fly in a temporary directory. It won't interfere with your project repository (no matter what VCS you use: Git, SVN, Mercurial, ... or none). Your sources are restored in case of unexpected errors.

    How does it work? #

    The key step is generating a Git patch. The patch contains all the changes made in the React Native templates between the version your app is using and the new version.

    To obtain this patch, we need to generate an app from the templates embedded in the react-native package inside your node_modules directory (these are the same templates the react-native init commands uses). Then, after the native apps have been generated from the templates in both the current version and the new version, Git is able to produce a patch that is adapted to your project (i.e. containing your app name):

    [...] +Easier Upgrades Thanks to Git
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Easier Upgrades Thanks to Git

    Upgrading to new versions of React Native has been difficult. You might have seen something like this before:

    None of those options is ideal. By overwriting the file we lose our local changes. By not overwriting we don't get the latest updates.

    Today I am proud to introduce a new tool that helps solve this problem. The tool is called react-native-git-upgrade and uses Git behind the scenes to resolve conflicts automatically whenever possible.

    Usage #

    Requirement: Git has to be available in the PATH. Your project doesn't have to be managed by Git.

    Install react-native-git-upgrade globally:

    $ npm install -g react-native-git-upgrade

    or, using Yarn:

    $ yarn global add react-native-git-upgrade

    Then, run it inside your project directory:

    $ cd MyProject +$ react-native-git-upgrade 0.38.0

    Note: Do not run 'npm install' to install a new version of react-native. The tool needs to be able to compare the old and new project template to work correctly. Simply run it inside your app folder as shown above, while still on the old version.

    Example output:

    You can also run react-native-git-upgrade with no arguments to upgrade to the latest version of React Native.

    We try to preserve your changes in iOS and Android build files, so you don't need to run react-native link after an upgrade.

    We have designed the implementation to be as little intrusive as possible. It is entirely based on a local Git repository created on-the-fly in a temporary directory. It won't interfere with your project repository (no matter what VCS you use: Git, SVN, Mercurial, ... or none). Your sources are restored in case of unexpected errors.

    How does it work? #

    The key step is generating a Git patch. The patch contains all the changes made in the React Native templates between the version your app is using and the new version.

    To obtain this patch, we need to generate an app from the templates embedded in the react-native package inside your node_modules directory (these are the same templates the react-native init commands uses). Then, after the native apps have been generated from the templates in both the current version and the new version, Git is able to produce a patch that is adapted to your project (i.e. containing your app name):

    [...] diff --git a/ios/MyAwesomeApp/Info.plist b/ios/MyAwesomeApp/Info.plist index e98ebb0..2fb6a11 100644 --- a/ios/MyAwesomeApp/Info.plist +++ b/ios/MyAwesomeApp/Info.plist @@ -45,7 +45,7 @@ - <dict> - <key>localhost</key> - <dict> -- <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> -+ <key>NSExceptionAllowsInsecureHTTPLoads</key> - <true/> - </dict> - </dict> -[...]

    All we need now is to apply this patch to your source files. While the old react-native upgrade process would have prompted you for any small difference, Git is able to merge most of the changes automatically using its 3-way merge algorithm and eventually leave us with familiar conflict delimiters:

    13B07F951A680F5B00A75B9A /* Release */ = { + <dict> + <key>localhost</key> + <dict> +- <key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key> ++ <key>NSExceptionAllowsInsecureHTTPLoads</key> + <true/> + </dict> + </dict> +[...]

    All we need now is to apply this patch to your source files. While the old react-native upgrade process would have prompted you for any small difference, Git is able to merge most of the changes automatically using its 3-way merge algorithm and eventually leave us with familiar conflict delimiters:

    13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; -<<<<<<< ours +<<<<<<< ours CODE_SIGN_IDENTITY = "iPhone Developer"; FRAMEWORK_SEARCH_PATHS = ( "$(inherited)", @@ -27,7 +27,7 @@ index e98ebb0.); ======= CURRENT_PROJECT_VERSION = 1; ->>>>>>> theirs +>>>>>>> theirs HEADER_SEARCH_PATHS = ( "$(inherited)", /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include, diff --git a/blog/2017/01/07/monthly-release-cadence.html b/blog/2017/01/07/monthly-release-cadence.html index b6e2a30f240..adf9a4a5637 100644 --- a/blog/2017/01/07/monthly-release-cadence.html +++ b/blog/2017/01/07/monthly-release-cadence.html @@ -1,4 +1,4 @@ -A Monthly Release Cadence: Releasing December and January RC
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    A Monthly Release Cadence: Releasing December and January RC

    Shortly after React Native was introduced, we started releasing every two weeks to help the community adopt new features, while keeping versions stable for production use. At Facebook we had to stabilize the codebase every two weeks for the release of our production iOS apps, so we decided to release the open source versions at the same pace. Now, many of the Facebook apps ship once per week, especially on Android. Because we ship from master weekly, we need to keep it quite stable. So the bi-weekly release cadence doesn't even benefit internal contributors anymore.

    We frequently hear feedback from the community that the release rate is hard to keep up with. Tools like Expo had to skip every other release in order to manage the rapid change in version. So it seems clear that the bi-weekly releases did not serve the community well.

    Now releasing monthly #

    We're happy to announce the new monthly release cadence, and the December 2016 release, v0.40, which has been stabilizing for all last month and is ready to adopt. (Just make sure to update headers in your native modules on iOS).

    Although it may vary a few days to avoid weekends or handle unforeseen issues, you can now expect a given release to be available on the first day of the month, and released on the last.

    Use the current month for the best support #

    The January release candidate is ready to try, and you can see what's new here.

    To see what changes are coming and provide better feedback to React Native contributors, always use the current month's release candidate when possible. By the time each version is released at the end of the month, the changes it contains will have been shipped in production Facebook apps for over two weeks.

    You can easily upgrade your app with the new react-native-git-upgrade command:

    npm install -g react-native-git-upgrade +A Monthly Release Cadence: Releasing December and January RC
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    A Monthly Release Cadence: Releasing December and January RC

    Shortly after React Native was introduced, we started releasing every two weeks to help the community adopt new features, while keeping versions stable for production use. At Facebook we had to stabilize the codebase every two weeks for the release of our production iOS apps, so we decided to release the open source versions at the same pace. Now, many of the Facebook apps ship once per week, especially on Android. Because we ship from master weekly, we need to keep it quite stable. So the bi-weekly release cadence doesn't even benefit internal contributors anymore.

    We frequently hear feedback from the community that the release rate is hard to keep up with. Tools like Expo had to skip every other release in order to manage the rapid change in version. So it seems clear that the bi-weekly releases did not serve the community well.

    Now releasing monthly #

    We're happy to announce the new monthly release cadence, and the December 2016 release, v0.40, which has been stabilizing for all last month and is ready to adopt. (Just make sure to update headers in your native modules on iOS).

    Although it may vary a few days to avoid weekends or handle unforeseen issues, you can now expect a given release to be available on the first day of the month, and released on the last.

    Use the current month for the best support #

    The January release candidate is ready to try, and you can see what's new here.

    To see what changes are coming and provide better feedback to React Native contributors, always use the current month's release candidate when possible. By the time each version is released at the end of the month, the changes it contains will have been shipped in production Facebook apps for over two weeks.

    You can easily upgrade your app with the new react-native-git-upgrade command:

    npm install -g react-native-git-upgrade react-native-git-upgrade 0.41.0-rc.0

    We hope this simpler approach will make it easier for the community to keep track of changes in React Native, and to adopt new versions as quickly as possible!

    (Thanks go to Martin Konicek for coming up with this plan and Mike Grabowski for making it happen)

    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Using Native Driver for Animated

    For the past year, we've been working on improving performance of animations that use the Animated library. Animations are very important to create a beautiful user experience but can also be hard to do right. We want to make it easy for developers to create performant animations without having to worry about some of their code causing it to lag.

    What is this? #

    The Animated API was designed with a very important constraint in mind, it is serializable. This means we can send everything about the animation to native before it has even started and allows native code to perform the animation on the UI thread without having to go through the bridge on every frame. It is very useful because once the animation has started, the JS thread can be blocked and the animation will still run smoothly. In practice this can happen a lot because user code runs on the JS thread and React renders can also lock JS for a long time.

    A bit of history... #

    This project started about a year ago, when Expo built the li.st app on Android. Krzysztof Magiera was contracted to build the initial implementation on Android. It ended up working well and li.st was the first app to ship with native driven animations using Animated. A few months later, Brandon Withrow built the initial implementation on iOS. After that, Ryan Gomba and myself worked on adding missing features like support for Animated.event as well as squash bugs we found when using it in production apps. This was truly a community effort and I would like to thanks everyone that was involved as well as Expo for sponsoring a large part of the development. It is now used by Touchable components in React Native as well as for navigation animations in the newly released React Navigation library.

    How does it work? #

    First, let's check out how animations currently work using Animated with the JS driver. When using Animated, you declare a graph of nodes that represent the animations that you want to perform, and then use a driver to update an Animated value using a predefined curve. You may also update an Animated value by connecting it to an event of a View using Animated.event.

    Here's a breakdown of the steps for an animation and where it happens:

    • JS: The animation driver uses requestAnimationFrame to execute on every frame and update the value it drives using the new value it calculates based on the animation curve.
    • JS: Intermediate values are calculated and passed to a props node that is attached to a View.
    • JS: The View is updated using setNativeProps.
    • JS to Native bridge.
    • Native: The UIView or android.View is updated.

    As you can see, most of the work happens on the JS thread. If it is blocked the animation will skip frames. It also needs to go through the JS to Native bridge on every frame to update native views.

    What the native driver does is move all of these steps to native. Since Animated produces a graph of animated nodes, it can be serialized and sent to native only once when the animation starts, eliminating the need to callback into the JS thread; the native code can take care of updating the views directly on the UI thread on every frame.

    Here's an example of how we can serialize an animated value and an interpolation node (not the exact implementation, just an example).

    Create the native value node, this is the value that will be animated:

    NativeAnimatedModule.createNode({ +Using Native Driver for Animated
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Using Native Driver for Animated

    For the past year, we've been working on improving performance of animations that use the Animated library. Animations are very important to create a beautiful user experience but can also be hard to do right. We want to make it easy for developers to create performant animations without having to worry about some of their code causing it to lag.

    What is this? #

    The Animated API was designed with a very important constraint in mind, it is serializable. This means we can send everything about the animation to native before it has even started and allows native code to perform the animation on the UI thread without having to go through the bridge on every frame. It is very useful because once the animation has started, the JS thread can be blocked and the animation will still run smoothly. In practice this can happen a lot because user code runs on the JS thread and React renders can also lock JS for a long time.

    A bit of history... #

    This project started about a year ago, when Expo built the li.st app on Android. Krzysztof Magiera was contracted to build the initial implementation on Android. It ended up working well and li.st was the first app to ship with native driven animations using Animated. A few months later, Brandon Withrow built the initial implementation on iOS. After that, Ryan Gomba and myself worked on adding missing features like support for Animated.event as well as squash bugs we found when using it in production apps. This was truly a community effort and I would like to thanks everyone that was involved as well as Expo for sponsoring a large part of the development. It is now used by Touchable components in React Native as well as for navigation animations in the newly released React Navigation library.

    How does it work? #

    First, let's check out how animations currently work using Animated with the JS driver. When using Animated, you declare a graph of nodes that represent the animations that you want to perform, and then use a driver to update an Animated value using a predefined curve. You may also update an Animated value by connecting it to an event of a View using Animated.event.

    Here's a breakdown of the steps for an animation and where it happens:

    • JS: The animation driver uses requestAnimationFrame to execute on every frame and update the value it drives using the new value it calculates based on the animation curve.
    • JS: Intermediate values are calculated and passed to a props node that is attached to a View.
    • JS: The View is updated using setNativeProps.
    • JS to Native bridge.
    • Native: The UIView or android.View is updated.

    As you can see, most of the work happens on the JS thread. If it is blocked the animation will skip frames. It also needs to go through the JS to Native bridge on every frame to update native views.

    What the native driver does is move all of these steps to native. Since Animated produces a graph of animated nodes, it can be serialized and sent to native only once when the animation starts, eliminating the need to callback into the JS thread; the native code can take care of updating the views directly on the UI thread on every frame.

    Here's an example of how we can serialize an animated value and an interpolation node (not the exact implementation, just an example).

    Create the native value node, this is the value that will be animated:

    NativeAnimatedModule.createNode({ id: 1, type: 'value', initialValue: 0, -});

    Create the native interpolation node, this tells the native driver how to interpolate a value:

    NativeAnimatedModule.createNode({ +});

    Create the native interpolation node, this tells the native driver how to interpolate a value:

    NativeAnimatedModule.createNode({ id: 2, type: 'interpolation', inputRange: [0, 10], outputRange: [10, 0], extrapolate: 'clamp', -});

    Create the native props node, this tells the native driver which prop on the view it is attached to:

    NativeAnimatedModule.createNode({ +});

    Create the native props node, this tells the native driver which prop on the view it is attached to:

    NativeAnimatedModule.createNode({ id: 3, type: 'props', properties: ['style.opacity'], -});

    Connect nodes together:

    NativeAnimatedModule.connectNodes(1, 2); -NativeAnimatedModule.connectNodes(2, 3);

    Connect the props node to a view:

    NativeAnimatedModule.connectToView(3, ReactNative.findNodeHandle(viewRef));

    With that, the native animated module has all the info it needs to update the native views directly without having to go to JS to calculate any value.

    All there is left to do is actually start the animation by specifying what type of animation curve we want and what animated value to update. Timing animations can also be simplified by calculating every frame of the animation in advance in JS to make the native implementation smaller.

    NativeAnimatedModule.startAnimation({ +});

    Connect nodes together:

    NativeAnimatedModule.connectNodes(1, 2); +NativeAnimatedModule.connectNodes(2, 3);

    Connect the props node to a view:

    NativeAnimatedModule.connectToView(3, ReactNative.findNodeHandle(viewRef));

    With that, the native animated module has all the info it needs to update the native views directly without having to go to JS to calculate any value.

    All there is left to do is actually start the animation by specifying what type of animation curve we want and what animated value to update. Timing animations can also be simplified by calculating every frame of the animation in advance in JS to make the native implementation smaller.

    NativeAnimatedModule.startAnimation({ type: 'timing', - frames: [0, 0.1, 0.2, 0.4, 0.65, ...], + frames: [0, 0.1, 0.2, 0.4, 0.65, ...], animatedValueId: 1, -});

    And now here's the breakdown of what happens when the animation runs:

    • Native: The native animation driver uses CADisplayLink or android.view.Choreographer to execute on every frame and update the value it drives using the new value it calculates based on the animation curve.
    • Native: Intermediate values are calculated and passed to a props node that is attached to a native view.
    • Native: The UIView or android.View is updated.

    As you can see, no more JS thread and no more bridge which means faster animations! 🎉🎉

    How do I use this in my app? #

    For normal animations the answer is simple, just add useNativeDriver: true to the animation config when starting it.

    Before:

    Animated.timing(this.state.animatedValue, { +});

    And now here's the breakdown of what happens when the animation runs:

    • Native: The native animation driver uses CADisplayLink or android.view.Choreographer to execute on every frame and update the value it drives using the new value it calculates based on the animation curve.
    • Native: Intermediate values are calculated and passed to a props node that is attached to a native view.
    • Native: The UIView or android.View is updated.

    As you can see, no more JS thread and no more bridge which means faster animations! 🎉🎉

    How do I use this in my app? #

    For normal animations the answer is simple, just add useNativeDriver: true to the animation config when starting it.

    Before:

    Animated.timing(this.state.animatedValue, { toValue: 1, duration: 500, -}).start();

    After:

    Animated.timing(this.state.animatedValue, { +}).start();

    After:

    Animated.timing(this.state.animatedValue, { toValue: 1, duration: 500, useNativeDriver: true, // <-- Add this -}).start();

    Animated values are only compatible with one driver so if you use native driver when starting an animation on a value, make sure every animation on that value also uses the native driver.

    It also works with Animated.event, this is very useful if you have an animation that must follow the scroll position because without the native driver it will always run a frame behind of the gesture because of the async nature of React Native.

    Before:

    <ScrollView +}).start();

    Animated values are only compatible with one driver so if you use native driver when starting an animation on a value, make sure every animation on that value also uses the native driver.

    It also works with Animated.event, this is very useful if you have an animation that must follow the scroll position because without the native driver it will always run a frame behind of the gesture because of the async nature of React Native.

    Before:

    <ScrollView scrollEventThrottle={16} - onScroll={Animated.event( + onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.state.animatedValue } } }] )} > {content} -</ScrollView>

    After:

    <Animated.ScrollView // <-- Use the Animated ScrollView wrapper +</ScrollView>

    After:

    <Animated.ScrollView // <-- Use the Animated ScrollView wrapper scrollEventThrottle={1} // <-- Use 1 here to make sure no events are ever missed - onScroll={Animated.event( + onScroll={Animated.event( [{ nativeEvent: { contentOffset: { y: this.state.animatedValue } } }], { useNativeDriver: true } // <-- Add this )} > {content} -</Animated.ScrollView>

    Caveats #

    Not everything you can do with Animated is currently supported in Native Animated. The main limitation is that you can only animate non-layout properties, things like transform, opacity and backgroundColor will work but flexbox and position properties won't. Another one is with Animated.event, it will only work with direct events and not bubbling events. This means it does not work with PanResponder but does work with things like ScrollView#onScroll.

    Native Animated has also been part of React Native for quite a while but has never been documented because it was considered experimental. Because of that make sure you are using a recent version (0.40+) of React Native if you want to use this feature.

    Resources #

    For more information about animated I recommend watching this talk by Christopher Chedeau.

    If you want a deep dive into animations and how offloading them to native can improve user experience there is also this talk by Krzysztof Magiera.

    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Better List Views in React Native

    Many of you have started playing with some of our new List components already after our teaser announcement in the community group, but we are officially announcing them today! No more ListViews or DataSources, stale rows, ignored bugs, or excessive memory consumption - with the latest React Native March 2017 release candidate (0.43-rc.1) you can pick from the new suite of components what best fits your use-case, with great perf and feature sets out of the box:

    <FlatList> #

    This is the workhorse component for simple, performant lists. Provide an array of data and a renderItem function and you're good to go:

    <FlatList - data={[{title: 'Title Text', key: 'item1'}, ...]} - renderItem={({item}) => <ListItem title={item.title} />} -/>

    <SectionList> #

    If you want to render a set of data broken into logical sections, maybe with section headers (e.g. in an alphabetical address book), and potentially with heterogeneous data and rendering (such as a profile view with some buttons followed by a composer, then a photo grid, then a friend grid, and finally a list of stories), this is the way to go.

    <SectionList - renderItem={({item}) => <ListItem title={item.title} />} - renderSectionHeader={({section}) => <H1 title={section.key} />} +Better List Views in React Native
    React Native Blog
    Stay up-to-date with the latest React Native news and events.

    Better List Views in React Native

    Many of you have started playing with some of our new List components already after our teaser announcement in the community group, but we are officially announcing them today! No more ListViews or DataSources, stale rows, ignored bugs, or excessive memory consumption - with the latest React Native March 2017 release candidate (0.43-rc.1) you can pick from the new suite of components what best fits your use-case, with great perf and feature sets out of the box:

    <FlatList> #

    This is the workhorse component for simple, performant lists. Provide an array of data and a renderItem function and you're good to go:

    <FlatList + data={[{title: 'Title Text', key: 'item1'}, ...]} + renderItem={({item}) => <ListItem title={item.title} />} +/>

    <SectionList> #

    If you want to render a set of data broken into logical sections, maybe with section headers (e.g. in an alphabetical address book), and potentially with heterogeneous data and rendering (such as a profile view with some buttons followed by a composer, then a photo grid, then a friend grid, and finally a list of stories), this is the way to go.

    <SectionList + renderItem={({item}) => <ListItem title={item.title} />} + renderSectionHeader={({section}) => <H1 title={section.key} />} sections={[ // homogenous rendering between sections - {data: [...], key: ...}, - {data: [...], key: ...}, - {data: [...], key: ...}, + {data: [...], key: ...}, + {data: [...], key: ...}, + {data: [...], key: ...}, ]} /> -<SectionList +<SectionList sections={[ // heterogeneous rendering between sections - {data: [...], key: ..., renderItem: ...}, - {data: [...], key: ..., renderItem: ...}, - {data: [...], key: ..., renderItem: ...}, + {data: [...], key: ..., renderItem: ...}, + {data: [...], key: ..., renderItem: ...}, + {data: [...], key: ..., renderItem: ...}, ]} -/>

    <VirtualizedList> #

    The implementation behind the scenes with a more flexible API. Especially handy if your data is not in a plain array (e.g. an immutable list).

    Features #

    Lists are used in many contexts, so we packed the new components full of features to handle the majority of use cases out of the box:

    • Scroll loading (onEndReached).
    • Pull to refresh (onRefresh / refreshing).
    • Configurable viewability (VPV) callbacks (onViewableItemsChanged / viewabilityConfig).
    • Horizontal mode (horizontal).
    • Intelligent item and section separators.
    • Multi-column support (numColumns)
    • scrollToEnd, scrollToIndex, and scrollToItem
    • Better Flow typing.

    Some Caveats #

    You can edit the content above on GitHub and send us a pull request!

    Animations #

    Animations are very important to create a great user experience. +Animations

    Animations #

    Animations are very important to create a great user experience. Stationary objects must overcome inertia as they start moving. Objects in motion have momentum and rarely come to a stop immediately. Animations allow you to convey physically believable motion in your interface.

    React Native provides two complementary animation systems: Animated for granular and interactive control of specific values, and LayoutAnimation for animated global layout transactions.

    Animated API #

    The Animated API is designed to make it very easy to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. -Animated focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simple start/stop methods to control time-based animation execution.

    Animated exports four animatable component types: View, Text, Image, and ScrollView, but you can also create your own using Animated.createAnimatedComponent().

    For example, a container view that fades in when it is mounted may look like this: