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).
+Martín Bigio —
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:
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:
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:
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:
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:
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:
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:
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:
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:
Kevin Lacker —
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:
Kevin Lacker —
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:
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!

Héctor Ramos —
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:
- Did you know that React Native is now the top Java repository on GitHub?
- rnpm is now part of React Native core! You can now use
react-native linkin place ofrnpm linkto install libraries with native dependencies. - The React Native Meetup community is growing fast! There are now over 4,800 developers across a variety of React Native meetup groups all over the globe.
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
ScrollViewin a scene should be wrapped in aScrollScenecomponent. 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:
- Deco announced their React Native Showcase, and invited everyone to add their app to the list.
- The recent documentation overhaul got a shoutout!
- Devin Abbott, one of the creators of Deco IDE, will be teaching an introductory React Native course.

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!

Héctor Ramos —
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:
- Did you know that React Native is now the top Java repository on GitHub?
- rnpm is now part of React Native core! You can now use
react-native linkin place ofrnpm linkto install libraries with native dependencies. - The React Native Meetup community is growing fast! There are now over 4,800 developers across a variety of React Native meetup groups all over the globe.
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
ScrollViewin a scene should be wrapped in aScrollScenecomponent. 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:
- Deco announced their React Native Showcase, and invited everyone to add their app to the list.
- The recent documentation overhaul got a shoutout!
- Devin Abbott, one of the creators of Deco IDE, will be teaching an introductory React Native course.

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!
Mengjue (Mandy) Wang —
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:
+
Mengjue (Mandy) Wang —
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:
- css-layout RTL support for absolute positioning
- mapping
leftandrighttostartandendin RN core implementation for shadow nodes - and exposing a bridged utility module to help control the RTL layout
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 #
To support RTL, you should first add the RTL language bundles to your app.
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
startandendfor the layout. In the Left-to-Right (LTR) layout,startmeansleft, andendmeansright. But in RTL,startmeansright, andendmeansleft. This means we can make RN depend on thestartandendcalculation to compute the correct layout, which includesposition,padding, andmargin.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:
- css-layout RTL support for absolute positioning
- mapping
leftandrighttostartandendin RN core implementation for shadow nodes - and exposing a bridged utility module to help control the RTL layout
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 #
To support RTL, you should first add the RTL language bundles to your app.
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);For Android, you need add
android:supportsRtl="true"to the<application>element inAndroidManifest.xmlfile.
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
transformstyle to the image component:<Image - source={...} +Here are two ways to flip the icon according to the direction:
Adding a
transformstyle 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
SwipeableRowandNavigationExperimental. 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 BlogStay up-to-date with the latest React Native news and events.Héctor Ramos —
Expo Talks: Adam on Unraveling Navigation
Adam Miskiewicz from Expo talks about mobile navigation and the
ex-navigationReact Native library at Expo's office hours last week.React Native BlogStay up-to-date with the latest React Native news and events.Héctor Ramos —
Expo Talks: Adam on Unraveling Navigation
Adam Miskiewicz from Expo talks about mobile navigation and the
ex-navigationReact Native library at Expo's office hours last week.React Native BlogStay up-to-date with the latest React Native news and events.Héctor Ramos —
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 BlogStay up-to-date with the latest React Native news and events.Héctor Ramos —
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 callKeyboard.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 callKeyboard.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();bwill then followa's spring animation and produce the value of1 / 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
barStylevalue has been added toStatusBar:dark-content. With this addition, you can now usebarStyleon 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();bwill then followa's spring animation and produce the value of1 / 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
barStylevalue has been added toStatusBar:dark-content. With this addition, you can now usebarStyleon 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 upgradeReact Native BlogStay up-to-date with the latest React Native news and events.Héctor Ramos —
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.
<Button +Introducing Button, Faster Installs with Yarn, and a Public Roadmap React Native BlogStay up-to-date with the latest React Native news and events.Héctor Ramos —
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.
<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 BlogStay up-to-date with the latest React Native news and events.Nicolas Cuillery —
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-upgradeand 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-upgradeglobally:$ npm install -g react-native-git-upgradeor, using Yarn:
$ yarn global add react-native-git-upgradeThen, run it inside your project directory:
$ cd MyProject -$ react-native-git-upgrade 0.38.0Note: 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-upgradewith 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 linkafter 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-nativepackage inside yournode_modulesdirectory (these are the same templates thereact-native initcommands 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 BlogStay up-to-date with the latest React Native news and events.Nicolas Cuillery —
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-upgradeand 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-upgradeglobally:$ npm install -g react-native-git-upgradeor, using Yarn:
$ yarn global add react-native-git-upgradeThen, run it inside your project directory:
$ cd MyProject +$ react-native-git-upgrade 0.38.0Note: 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-upgradewith 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 linkafter 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-nativepackage inside yournode_modulesdirectory (these are the same templates thereact-native initcommands 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 upgradeprocess 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 upgradeprocess 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 BlogStay up-to-date with the latest React Native news and events.Eric Vicenti —
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 BlogStay up-to-date with the latest React Native news and events.Eric Vicenti —
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.0We 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 BlogStay up-to-date with the latest React Native news and events.Janic Duplessis —
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.eventas 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 byTouchablecomponents 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
ViewusingAnimated.event.
Here's a breakdown of the steps for an animation and where it happens:
- JS: The animation driver uses
requestAnimationFrameto 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
Viewis updated usingsetNativeProps. - JS to Native bridge.
- Native: The
UIVieworandroid.Viewis 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 BlogStay up-to-date with the latest React Native news and events.Janic Duplessis —
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.eventas 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 byTouchablecomponents 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
ViewusingAnimated.event.
Here's a breakdown of the steps for an animation and where it happens:
- JS: The animation driver uses
requestAnimationFrameto 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
Viewis updated usingsetNativeProps. - JS to Native bridge.
- Native: The
UIVieworandroid.Viewis 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
CADisplayLinkorandroid.view.Choreographerto 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
UIVieworandroid.Viewis 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: trueto 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
CADisplayLinkorandroid.view.Choreographerto 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
UIVieworandroid.Viewis 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: trueto 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,opacityandbackgroundColorwill work but flexbox and position properties won't. Another one is withAnimated.event, it will only work with direct events and not bubbling events. This means it does not work withPanResponderbut does work with things likeScrollView#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 BlogStay up-to-date with the latest React Native news and events.Spencer Ahrens —
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 orDataSources, 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
renderItemfunction 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 BlogStay up-to-date with the latest React Native news and events.Spencer Ahrens —
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 orDataSources, 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
renderItemfunction 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, andscrollToItem- Better Flow typing.
Some Caveats #
The internal state of item subtrees is not preserved when content scrolls out of the render window. Make sure all your data is captured in the item data or external stores like Flux, Redux, or Relay.
These components are based on
PureComponentwhich means that they will not re-render ifpropsremains shallow-equal. Make sure that everything yourrenderItemfunction depends on directly is passed as a prop that is not===after updates, otherwise your UI may not update on changes. This includes thedataprop and parent component state. For example:<FlatList +/><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, andscrollToItem- Better Flow typing.
Some Caveats #
The internal state of item subtrees is not preserved when content scrolls out of the render window. Make sure all your data is captured in the item data or external stores like Flux, Redux, or Relay.
These components are based on
PureComponentwhich means that they will not re-render ifpropsremains shallow-equal. Make sure that everything yourrenderItemfunction depends on directly is passed as a prop that is not===after updates, otherwise your UI may not update on changes. This includes thedataprop and parent component state. For example:<FlatList data={this.state.data} - renderItem={({item}) => <MyItem + renderItem={({item}) => <MyItem item={item} - onPress={() => this.setState((oldState) => ({ + onPress={() => this.setState((oldState) => ({ selected: { // New instance breaks `===` - ...oldState.selected, // copy old data + ...oldState.selected, // copy old data [item.key]: !oldState.selected[item.key], // toggle }})) } diff --git a/blog/2017/03/13/idx-the-existential-function.html b/blog/2017/03/13/idx-the-existential-function.html index f8614f0870b..1d788d12593 100644 --- a/blog/2017/03/13/idx-the-existential-function.html +++ b/blog/2017/03/13/idx-the-existential-function.html @@ -1,7 +1,7 @@ -idx: The Existential Function React Native BlogStay up-to-date with the latest React Native news and events.Timothy Yung —
idx: The Existential Function
At Facebook, we often need to access deeply nested values in data structures fetched with GraphQL. On the way to accessing these deeply nested values, it is common for one or more intermediate fields to be nullable. These intermediate fields may be null for a variety of reasons, from failed privacy checks to the mere fact that null happens to be the most flexible way to represent non-fatal errors.
Unfortunately, accessing these deeply nested values is currently tedious and verbose.
props.user && -props.user.friends && -props.user.friends[0] && -props.user.friends[0].friendsThere is an ECMAScript proposal to introduce the existential operator which will make this much more convenient. But until a time when that proposal is finalized, we want a solution that improves our quality of life, maintains existing language semantics, and encourages type safety with Flow.
We came up with an existential function we call
idx.idx(props, _ => _.user.friends[0].friends)The invocation in this code snippet behaves similarly to the boolean expression in the code snippet above, except with significantly less repetition. The
idxfunction takes exactly two arguments:- Any value, typically an object or array into which you want to access a nested value.
- A function that receives the first argument and accesses a nested value on it.
In theory, the
idxfunction will try-catch errors that are the result of accessing properties on null or undefined. If such an error is caught, it will return either null or undefined. (And you can see how this might be implemented in idx.js.)In practice, try-catching every nested property access is slow, and differentiating between specific kinds of TypeErrors is fragile. To deal with these shortcomings, we created a Babel plugin that transforms the above
idxinvocation into the following expression:props.user == null ? props.user : +idx: The Existential Function React Native BlogStay up-to-date with the latest React Native news and events.Timothy Yung —
idx: The Existential Function
At Facebook, we often need to access deeply nested values in data structures fetched with GraphQL. On the way to accessing these deeply nested values, it is common for one or more intermediate fields to be nullable. These intermediate fields may be null for a variety of reasons, from failed privacy checks to the mere fact that null happens to be the most flexible way to represent non-fatal errors.
Unfortunately, accessing these deeply nested values is currently tedious and verbose.
props.user && +props.user.friends && +props.user.friends[0] && +props.user.friends[0].friendsThere is an ECMAScript proposal to introduce the existential operator which will make this much more convenient. But until a time when that proposal is finalized, we want a solution that improves our quality of life, maintains existing language semantics, and encourages type safety with Flow.
We came up with an existential function we call
idx.idx(props, _ => _.user.friends[0].friends)The invocation in this code snippet behaves similarly to the boolean expression in the code snippet above, except with significantly less repetition. The
idxfunction takes exactly two arguments:- Any value, typically an object or array into which you want to access a nested value.
- A function that receives the first argument and accesses a nested value on it.
In theory, the
idxfunction will try-catch errors that are the result of accessing properties on null or undefined. If such an error is caught, it will return either null or undefined. (And you can see how this might be implemented in idx.js.)In practice, try-catching every nested property access is slow, and differentiating between specific kinds of TypeErrors is fragile. To deal with these shortcomings, we created a Babel plugin that transforms the above
idxinvocation into the following expression:props.user == null ? props.user : props.user.friends == null ? props.user.friends : props.user.friends[0] == null ? props.user.friends[0] : props.user.friends[0].friendsFinally, we added a custom Flow type declaration for
idxthat allows the traversal in the second argument to be properly type-checked while permitting nested access on nullable properties.The function, Babel plugin, and Flow declaration are now available on GitHub. They are used by installing the idx and babel-plugin-idx npm packages, and adding “idx” to the list of plugins in your
.babelrcfile.React Native BlogStay up-to-date with the latest React Native news and events.Adam Perry —
Introducing Create React Native App
Today we’re announcing Create React Native App: a new tool that makes it significantly easier to get started with a React Native project! It’s heavily inspired by the design of Create React App and is the product of a collaboration between Facebook and Expo (formerly Exponent).
Many developers struggle with installing and configuring React Native’s current native build dependencies, especially for Android. With Create React Native App, there’s no need to use Xcode or Android Studio, and you can develop for your iOS device using Linux or Windows. This is accomplished using the Expo app, which loads and runs CRNA projects written in pure JavaScript without compiling any native code.
Try creating a new project (replace with suitable yarn commands if you have it installed):
$ npm i -g create-react-native-app +Introducing Create React Native App React Native BlogStay up-to-date with the latest React Native news and events.Adam Perry —
Introducing Create React Native App
Today we’re announcing Create React Native App: a new tool that makes it significantly easier to get started with a React Native project! It’s heavily inspired by the design of Create React App and is the product of a collaboration between Facebook and Expo (formerly Exponent).
Many developers struggle with installing and configuring React Native’s current native build dependencies, especially for Android. With Create React Native App, there’s no need to use Xcode or Android Studio, and you can develop for your iOS device using Linux or Windows. This is accomplished using the Expo app, which loads and runs CRNA projects written in pure JavaScript without compiling any native code.
Try creating a new project (replace with suitable yarn commands if you have it installed):
$ npm i -g create-react-native-app $ create-react-native-app my-project $ cd my-project $ npm startThis will start the React Native packager and print a QR code. Open it in the Expo app to load your JavaScript. Calls to
console.logare forwarded to your terminal. You can make use of any standard React Native APIs as well as the Expo SDK.What about native code? #
Many React Native projects have Java or Objective-C/Swift dependencies that need to be compiled. The Expo app does include APIs for camera, video, contacts, and more, and bundles popular libraries like Airbnb’s react-native-maps, or Facebook authentication. However if you need a native code dependency that Expo doesn’t bundle then you’ll probably need to have your own build configuration for it. Just like Create React App, “ejecting” is supported by CRNA.
You can run
npm run ejectto get a project very similar to whatreact-native initwould generate. At that point you’ll need Xcode and/or Android Studio just as you would if you started withreact-native init, adding libraries withreact-native linkwill work, and you’ll have full control over the native code compilation process.Questions? Feedback? #
Create React Native App is now stable enough for general use, which means we’re very eager to hear about your experience using it! You can find me on Twitter or open an issue on the GitHub repository. Pull requests are very welcome!
React Native BlogStay up-to-date with the latest React Native news and events.Adam Perry —
Introducing Create React Native App
Today we’re announcing Create React Native App: a new tool that makes it significantly easier to get started with a React Native project! It’s heavily inspired by the design of Create React App and is the product of a collaboration between Facebook and Expo (formerly Exponent).
Timothy Yung —
idx: The Existential Function
At Facebook, we often need to access deeply nested values in data structures fetched with GraphQL. On the way to accessing these deeply nested values, it is common for one or more intermediate fields to be nullable. These intermediate fields may be null for a variety of reasons, from failed privacy checks to the mere fact that null happens to be the most flexible way to represent non-fatal errors.
Spencer Ahrens —
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:
Janic Duplessis —
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.
Eric Vicenti —
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.
Nicolas Cuillery —
Easier Upgrades Thanks to Git
Upgrading to new versions of React Native has been difficult. You might have seen something like this before:
Héctor Ramos —
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:
Héctor Ramos —
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.
Héctor Ramos —
Expo Talks: Adam on Unraveling Navigation
Adam Miskiewicz from Expo talks about mobile navigation and the ex-navigation React Native library at Expo's office hours last week.
Mengjue (Mandy) Wang —
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.

Héctor Ramos —
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.
Kevin Lacker —
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.
Martín Bigio —
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.
React Native BlogStay up-to-date with the latest React Native news and events.Adam Perry —
Introducing Create React Native App
Today we’re announcing Create React Native App: a new tool that makes it significantly easier to get started with a React Native project! It’s heavily inspired by the design of Create React App and is the product of a collaboration between Facebook and Expo (formerly Exponent).
Timothy Yung —
idx: The Existential Function
At Facebook, we often need to access deeply nested values in data structures fetched with GraphQL. On the way to accessing these deeply nested values, it is common for one or more intermediate fields to be nullable. These intermediate fields may be null for a variety of reasons, from failed privacy checks to the mere fact that null happens to be the most flexible way to represent non-fatal errors.
Spencer Ahrens —
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:
Janic Duplessis —
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.
Eric Vicenti —
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.
Nicolas Cuillery —
Easier Upgrades Thanks to Git
Upgrading to new versions of React Native has been difficult. You might have seen something like this before:
Héctor Ramos —
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:
Héctor Ramos —
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.
Héctor Ramos —
Expo Talks: Adam on Unraveling Navigation
Adam Miskiewicz from Expo talks about mobile navigation and the ex-navigation React Native library at Expo's office hours last week.
Mengjue (Mandy) Wang —
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.

Héctor Ramos —
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.
Kevin Lacker —
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.
Martín Bigio —
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.
Accessibility #
Native App Accessibility (iOS and Android) #
Both iOS and Android provide APIs for making apps accessible to people with disabilities. In addition, both platforms provide bundled assistive technologies, like the screen readers VoiceOver (iOS) and TalkBack (Android) for the visually impaired. Similarly, in React Native we have included APIs designed to provide developers with support for making apps more accessible. Take note, iOS and Android differ slightly in their approaches, and thus the React Native implementations may vary by platform.
In addition to this documentation, you might find this blog post about React Native accessibility to be useful.
Making Apps Accessible #
Accessibility properties #
accessible (iOS, Android) #
When
true, indicates that the view is an accessibility element. When a view is an accessibility element, it groups its children into a single selectable component. By default, all touchable elements are accessible.On Android, ‘accessible={true}’ property for a react-native View will be translated into native ‘focusable={true}’.
<View accessible={true}> - <Text>text one</Text> - <Text>text two</Text> -</View>In the above example, we can't get accessibility focus separately on 'text one' and 'text two'. Instead we get focus on a parent view with 'accessible' property.
accessibilityLabel (iOS, Android) #
When a view is marked as accessible, it is a good practice to set an accessibilityLabel on the view, so that people who use VoiceOver know what element they have selected. VoiceOver will read this string when a user selects the associated element.
To use, set the
accessibilityLabelproperty to a custom string on your View:<TouchableOpacity accessible={true} accessibilityLabel={'Tap me!'} onPress={this._onPress}> - <View style={styles.button}> - <Text style={styles.buttonText}>Press me!</Text> - </View> -</TouchableOpacity>In the above example, the
accessibilityLabelon the TouchableOpacity element would default to "Press me!". The label is constructed by concatenating all Text node children separated by spaces.accessibilityTraits (iOS) #
Accessibility traits tell a person using VoiceOver what kind of element they have selected. Is this element a label? A button? A header? These questions are answered by
accessibilityTraits.To use, set the
accessibilityTraitsproperty to one of (or an array of) accessibility trait strings:- none Used when the element has no traits.
- button Used when the element should be treated as a button.
- link Used when the element should be treated as a link.
- header Used when an element acts as a header for a content section (e.g. the title of a navigation bar).
- search Used when the text field element should also be treated as a search field.
- image Used when the element should be treated as an image. Can be combined with button or link, for example.
- selected Used when the element is selected. For example, a selected row in a table or a selected button within a segmented control.
- plays Used when the element plays its own sound when activated.
- key Used when the element acts as a keyboard key.
- text Used when the element should be treated as static text that cannot change.
- summary Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. For example, when Weather first launches, the element with today's weather conditions is marked with this trait.
- disabled Used when the control is not enabled and does not respond to user input.
- frequentUpdates Used when the element frequently updates its label or value, but too often to send notifications. Allows an accessibility client to poll for changes. A stopwatch would be an example.
- startsMedia Used when activating an element starts a media session (e.g. playing a movie, recording audio) that should not be interrupted by output from an assistive technology, like VoiceOver.
- adjustable Used when an element can be "adjusted" (e.g. a slider).
- allowsDirectInteraction Used when an element allows direct touch interaction for VoiceOver users (for example, a view representing a piano keyboard).
- pageTurn Informs VoiceOver that it should scroll to the next page when it finishes reading the contents of the element.
accessibilityViewIsModal (iOS) #
A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver.
For example, in a window that contains sibling views
AandB, settingaccessibilityViewIsModaltotrueon viewBcauses VoiceOver to ignore the elements in the viewA. -On the other hand, if viewBcontains a child viewCand you setaccessibilityViewIsModaltotrueon viewC, VoiceOver does not ignore the elements in viewA.onAccessibilityTap (iOS) #
Use this property to assign a custom function to be called when someone activates an accessible element by double tapping on it while it's selected.
onMagicTap (iOS) #
Assign this property to a custom function which will be called when someone performs the "magic tap" gesture, which is a double-tap with two fingers. A magic tap function should perform the most relevant action a user could take on a component. In the Phone app on iPhone, a magic tap answers a phone call, or ends the current one. If the selected element does not have an
onMagicTapfunction, the system will traverse up the view hierarchy until it finds a view that does.accessibilityComponentType (Android) #
In some cases, we also want to alert the end user of the type of selected component (i.e., that it is a “button”). If we were using native buttons, this would work automatically. Since we are using javascript, we need to provide a bit more context for TalkBack. To do so, you must specify the ‘accessibilityComponentType’ property for any UI component. For instances, we support ‘button’, ‘radiobutton_checked’ and ‘radiobutton_unchecked’ and so on.
<TouchableWithoutFeedback accessibilityComponentType=”button” +Accessibility Accessibility #
Native App Accessibility (iOS and Android) #
Both iOS and Android provide APIs for making apps accessible to people with disabilities. In addition, both platforms provide bundled assistive technologies, like the screen readers VoiceOver (iOS) and TalkBack (Android) for the visually impaired. Similarly, in React Native we have included APIs designed to provide developers with support for making apps more accessible. Take note, iOS and Android differ slightly in their approaches, and thus the React Native implementations may vary by platform.
In addition to this documentation, you might find this blog post about React Native accessibility to be useful.
Making Apps Accessible #
Accessibility properties #
accessible (iOS, Android) #
When
true, indicates that the view is an accessibility element. When a view is an accessibility element, it groups its children into a single selectable component. By default, all touchable elements are accessible.On Android, ‘accessible={true}’ property for a react-native View will be translated into native ‘focusable={true}’.
<View accessible={true}> + <Text>text one</Text> + <Text>text two</Text> +</View>In the above example, we can't get accessibility focus separately on 'text one' and 'text two'. Instead we get focus on a parent view with 'accessible' property.
accessibilityLabel (iOS, Android) #
When a view is marked as accessible, it is a good practice to set an accessibilityLabel on the view, so that people who use VoiceOver know what element they have selected. VoiceOver will read this string when a user selects the associated element.
To use, set the
accessibilityLabelproperty to a custom string on your View:<TouchableOpacity accessible={true} accessibilityLabel={'Tap me!'} onPress={this._onPress}> + <View style={styles.button}> + <Text style={styles.buttonText}>Press me!</Text> + </View> +</TouchableOpacity>In the above example, the
accessibilityLabelon the TouchableOpacity element would default to "Press me!". The label is constructed by concatenating all Text node children separated by spaces.accessibilityTraits (iOS) #
Accessibility traits tell a person using VoiceOver what kind of element they have selected. Is this element a label? A button? A header? These questions are answered by
accessibilityTraits.To use, set the
accessibilityTraitsproperty to one of (or an array of) accessibility trait strings:- none Used when the element has no traits.
- button Used when the element should be treated as a button.
- link Used when the element should be treated as a link.
- header Used when an element acts as a header for a content section (e.g. the title of a navigation bar).
- search Used when the text field element should also be treated as a search field.
- image Used when the element should be treated as an image. Can be combined with button or link, for example.
- selected Used when the element is selected. For example, a selected row in a table or a selected button within a segmented control.
- plays Used when the element plays its own sound when activated.
- key Used when the element acts as a keyboard key.
- text Used when the element should be treated as static text that cannot change.
- summary Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. For example, when Weather first launches, the element with today's weather conditions is marked with this trait.
- disabled Used when the control is not enabled and does not respond to user input.
- frequentUpdates Used when the element frequently updates its label or value, but too often to send notifications. Allows an accessibility client to poll for changes. A stopwatch would be an example.
- startsMedia Used when activating an element starts a media session (e.g. playing a movie, recording audio) that should not be interrupted by output from an assistive technology, like VoiceOver.
- adjustable Used when an element can be "adjusted" (e.g. a slider).
- allowsDirectInteraction Used when an element allows direct touch interaction for VoiceOver users (for example, a view representing a piano keyboard).
- pageTurn Informs VoiceOver that it should scroll to the next page when it finishes reading the contents of the element.
accessibilityViewIsModal (iOS) #
A Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver.
For example, in a window that contains sibling views
AandB, settingaccessibilityViewIsModaltotrueon viewBcauses VoiceOver to ignore the elements in the viewA. +On the other hand, if viewBcontains a child viewCand you setaccessibilityViewIsModaltotrueon viewC, VoiceOver does not ignore the elements in viewA.onAccessibilityTap (iOS) #
Use this property to assign a custom function to be called when someone activates an accessible element by double tapping on it while it's selected.
onMagicTap (iOS) #
Assign this property to a custom function which will be called when someone performs the "magic tap" gesture, which is a double-tap with two fingers. A magic tap function should perform the most relevant action a user could take on a component. In the Phone app on iPhone, a magic tap answers a phone call, or ends the current one. If the selected element does not have an
onMagicTapfunction, the system will traverse up the view hierarchy until it finds a view that does.accessibilityComponentType (Android) #
In some cases, we also want to alert the end user of the type of selected component (i.e., that it is a “button”). If we were using native buttons, this would work automatically. Since we are using javascript, we need to provide a bit more context for TalkBack. To do so, you must specify the ‘accessibilityComponentType’ property for any UI component. For instances, we support ‘button’, ‘radiobutton_checked’ and ‘radiobutton_unchecked’ and so on.
<TouchableWithoutFeedback accessibilityComponentType=”button” onPress={this._onPress}> - <View style={styles.button}> - <Text style={styles.buttonText}>Press me!</Text> - </View> -</TouchableWithoutFeedback>In the above example, the TouchableWithoutFeedback is being announced by TalkBack as a native Button.
accessibilityLiveRegion (Android) #
When components dynamically change, we want TalkBack to alert the end user. This is made possible by the ‘accessibilityLiveRegion’ property. It can be set to ‘none’, ‘polite’ and ‘assertive’:
- none Accessibility services should not announce changes to this view.
- polite Accessibility services should announce changes to this view.
- assertive Accessibility services should interrupt ongoing speech to immediately announce changes to this view.
<TouchableWithoutFeedback onPress={this._addOne}> - <View style={styles.embedded}> - <Text>Click me</Text> - </View> -</TouchableWithoutFeedback> -<Text accessibilityLiveRegion="polite"> + <View style={styles.button}> + <Text style={styles.buttonText}>Press me!</Text> + </View> +</TouchableWithoutFeedback>In the above example, the TouchableWithoutFeedback is being announced by TalkBack as a native Button.
accessibilityLiveRegion (Android) #
When components dynamically change, we want TalkBack to alert the end user. This is made possible by the ‘accessibilityLiveRegion’ property. It can be set to ‘none’, ‘polite’ and ‘assertive’:
- none Accessibility services should not announce changes to this view.
- polite Accessibility services should announce changes to this view.
- assertive Accessibility services should interrupt ongoing speech to immediately announce changes to this view.
<TouchableWithoutFeedback onPress={this._addOne}> + <View style={styles.embedded}> + <Text>Click me</Text> + </View> +</TouchableWithoutFeedback> +<Text accessibilityLiveRegion="polite"> Clicked {this.state.count} times -</Text>In the above example method _addOne changes the state.count variable. As soon as an end user clicks the TouchableWithoutFeedback, TalkBack reads text in the Text view because of its 'accessibilityLiveRegion=”polite”' property.
importantForAccessibility (Android) #
In the case of two overlapping UI components with the same parent, default accessibility focus can have unpredictable behavior. The ‘importantForAccessibility’ property will resolve this by controlling if a view fires accessibility events and if it is reported to accessibility services. It can be set to ‘auto’, ‘yes’, ‘no’ and ‘no-hide-descendants’ (the last value will force accessibility services to ignore the component and all of its children).
<View style={styles.container}> - <View style={{position: 'absolute', left: 10, top: 10, right: 10, height: 100, +</Text>In the above example method _addOne changes the state.count variable. As soon as an end user clicks the TouchableWithoutFeedback, TalkBack reads text in the Text view because of its 'accessibilityLiveRegion=”polite”' property.
importantForAccessibility (Android) #
In the case of two overlapping UI components with the same parent, default accessibility focus can have unpredictable behavior. The ‘importantForAccessibility’ property will resolve this by controlling if a view fires accessibility events and if it is reported to accessibility services. It can be set to ‘auto’, ‘yes’, ‘no’ and ‘no-hide-descendants’ (the last value will force accessibility services to ignore the component and all of its children).
<View style={styles.container}> + <View style={{position: 'absolute', left: 10, top: 10, right: 10, height: 100, backgroundColor: 'green'}} importantForAccessibility=”yes”> - <Text> First layout </Text> - </View> - <View style={{position: 'absolute', left: 10, top: 10, right: 10, height: 100, + <Text> First layout </Text> + </View> + <View style={{position: 'absolute', left: 10, top: 10, right: 10, height: 100, backgroundColor: 'yellow'}} importantForAccessibility=”no-hide-descendants”> - <Text> Second layout </Text> - </View> -</View>In the above example, the yellow layout and its descendants are completely invisible to TalkBack and all other accessibility services. So we can easily use overlapping views with the same parent without confusing TalkBack.
Checking if a Screen Reader is Enabled #
The
AccessibilityInfoAPI allows you to determine whether or not a screen reader is currently active. See the AccessibilityInfo documentation for details.Sending Accessibility Events (Android) #
Sometimes it is useful to trigger an accessibility event on a UI component (i.e. when a custom view appears on a screen or a custom radio button has been selected). Native UIManager module exposes a method ‘sendAccessibilityEvent’ for this purpose. It takes two arguments: view tag and a type of an event.
_onPress: function() { + <Text> Second layout </Text> + </View> +</View>In the above example, the yellow layout and its descendants are completely invisible to TalkBack and all other accessibility services. So we can easily use overlapping views with the same parent without confusing TalkBack.
Checking if a Screen Reader is Enabled #
The
AccessibilityInfoAPI allows you to determine whether or not a screen reader is currently active. See the AccessibilityInfo documentation for details.Sending Accessibility Events (Android) #
Sometimes it is useful to trigger an accessibility event on a UI component (i.e. when a custom view appears on a screen or a custom radio button has been selected). Native UIManager module exposes a method ‘sendAccessibilityEvent’ for this purpose. It takes two arguments: view tag and a type of an event.
_onPress: function() { this.state.radioButton = this.state.radioButton === “radiobutton_checked” ? “radiobutton_unchecked” : “radiobutton_checked”; if (this.state.radioButton === “radiobutton_checked”) { - RCTUIManager.sendAccessibilityEvent( - ReactNative.findNodeHandle(this), + RCTUIManager.sendAccessibilityEvent( + ReactNative.findNodeHandle(this), RCTUIManager.AccessibilityEventTypes.typeViewClicked); } } -<CustomRadioButton +<CustomRadioButton accessibleComponentType={this.state.radioButton} onPress={this._onPress}/>In the above example we've created a custom radio button that now behaves like a native one. More specifically, TalkBack now correctly announces changes to the radio button selection.
Testing VoiceOver Support (iOS) #
To enable VoiceOver, go to the Settings app on your iOS device. Tap General, then Accessibility. There you will find many tools that people use to make their devices more usable, such as bolder text, increased contrast, and VoiceOver.
To enable VoiceOver, tap on VoiceOver under "Vision" and toggle the switch that appears at the top.
At the very bottom of the Accessibility settings, there is an "Accessibility Shortcut". You can use this to toggle VoiceOver by triple clicking the Home button.
You can edit the content above on GitHub and send us a pull request!
AccessibilityInfo #
Sometimes it's useful to know whether or not the device has a screen reader that is currently active. The +
AccessibilityInfo AccessibilityInfo #
Sometimes it's useful to know whether or not the device has a screen reader that is currently active. The
AccessibilityInfoAPI is designed for this purpose. You can use it to query the current state of the -screen reader as well as to register to be notified when the state of the screen reader changes.Here's a small example illustrating how to use
AccessibilityInfo:class ScreenReaderStatusExample extends React.Component { +screen reader as well as to register to be notified when the state of the screen reader changes.Here's a small example illustrating how to use
AccessibilityInfo:class ScreenReaderStatusExample extends React.Component { state = { screenReaderEnabled: false, } - componentDidMount() { - AccessibilityInfo.addEventListener( + componentDidMount() { + AccessibilityInfo.addEventListener( 'change', this._handleScreenReaderToggled ); - AccessibilityInfo.fetch().done((isEnabled) => { - this.setState({ + AccessibilityInfo.fetch().done((isEnabled) => { + this.setState({ screenReaderEnabled: isEnabled }); }); } - componentWillUnmount() { - AccessibilityInfo.removeEventListener( + componentWillUnmount() { + AccessibilityInfo.removeEventListener( 'change', this._handleScreenReaderToggled ); } - _handleScreenReaderToggled = (isEnabled) => { - this.setState({ + _handleScreenReaderToggled = (isEnabled) => { + this.setState({ screenReaderEnabled: isEnabled, }); } - render() { + render() { return ( - <View> - <Text> + <View> + <Text> The screen reader is {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}. - </Text> - </View> + </Text> + </View> ); } }Methods #
static fetch() #
Query whether a screen reader is currently enabled. Returns a promise which resolves to a boolean. The result is
truewhen a screen reader is enabled andfalseotherwise.static addEventListener(eventName, handler) #
Add an event handler. Supported events:
change: Fires when the state of the screen reader changes. The argument to the event handler is a boolean. The boolean istruewhen a screen -reader is enabled andfalseotherwise.
static setAccessibilityFocus(reactTag) #
iOS-Only. Set accessibility focus to a react component.
static removeEventListener(eventName, handler) #
Remove an event handler.
You can edit the content above on GitHub and send us a pull request!
ActionSheetIOS #
Methods #
static showActionSheetWithOptions(options, callback) #
Display an iOS action sheet. The
optionsobject must contain one or more +ActionSheetIOS ActionSheetIOS #
Methods #
static showActionSheetWithOptions(options, callback) #
Display an iOS action sheet. The
optionsobject must contain one or more of:options(array of strings) - a list of button titles (required)cancelButtonIndex(int) - index of cancel button inoptionsdestructiveButtonIndex(int) - index of destructive button inoptionstitle(string) - a title to show above the action sheetmessage(string) - a message to show below the title
static showShareActionSheetWithOptions(options, failureCallback, successCallback) #
Display the iOS share sheet. The
optionsobject should contain one or both ofmessageandurland can additionally have asubjectorexcludedActivityTypes:url(string) - a URL to sharemessage(string) - a message to sharesubject(string) - a subject for the messageexcludedActivityTypes(array) - the activities to exclude from the ActionSheet
NOTE: if
urlpoints to a local file, or is a base64-encoded diff --git a/releases/next/docs/activityindicator.html b/releases/next/docs/activityindicator.html index 4788af69491..d686dff98ca 100644 --- a/releases/next/docs/activityindicator.html +++ b/releases/next/docs/activityindicator.html @@ -1,4 +1,4 @@ -ActivityIndicator ActivityIndicator #
Displays a circular loading indicator.
Props #
animating?: PropTypes.bool #
Whether to show the indicator (true, the default) or hide it (false).
size?: PropTypes.oneOfType([ +
ActivityIndicator ActivityIndicator #
Displays a circular loading indicator.
Props #
animating?: PropTypes.bool #
Whether to show the indicator (true, the default) or hide it (false).
size?: PropTypes.oneOfType([ PropTypes.oneOf([ 'small', 'large' ]), PropTypes.number, ]) #
Size of the indicator (default is 'small'). diff --git a/releases/next/docs/adsupportios.html b/releases/next/docs/adsupportios.html index 0ec0e47d056..345fe3589e9 100644 --- a/releases/next/docs/adsupportios.html +++ b/releases/next/docs/adsupportios.html @@ -1,4 +1,4 @@ -
AdSupportIOS AdSupportIOS #
AdSupportprovides access to the "advertising identifier". If you link this library +AdSupportIOS AdSupportIOS #
AdSupportprovides access to the "advertising identifier". If you link this library in your project, you may need to justify your use for this identifier when submitting your application to the App Store.In order to use
AdSupportin your project, you must link theRCTAdSupportlibrary. In Xcode, you can manually add theRCTAdSupport.mandRCTAdSupport.hfiles from diff --git a/releases/next/docs/alert.html b/releases/next/docs/alert.html index 23c6f8ee338..26b05eb52f3 100644 --- a/releases/next/docs/alert.html +++ b/releases/next/docs/alert.html @@ -1,4 +1,4 @@ -Alert Alert #
Launches an alert dialog with the specified title and message.
Optionally provide a list of buttons. Tapping any button will fire the +
Alert Alert #
Launches an alert dialog with the specified title and message.
Optionally provide a list of buttons. Tapping any button will fire the respective onPress callback and dismiss the alert. By default, the only button will be an 'OK' button.
This is an API that works both on iOS and Android and can show static alerts. To show an alert that prompts the user to enter some information, @@ -9,13 +9,13 @@ box. This event can be handled by providing an optional
optionspar with anonDismisscallback property{ onDismiss: () => {} }.Alternatively, the dismissing behavior can be disabled altogether by providing an optional
optionsparameter with thecancelableproperty set tofalsei.e.{ cancelable: false }Example usage:
// Works on both iOS and Android -Alert.alert( +Alert.alert( 'Alert Title', 'My Alert Msg', [ - {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')}, - {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, - {text: 'OK', onPress: () => console.log('OK Pressed')}, + {text: 'Ask me later', onPress: () => console.log('Ask me later pressed')}, + {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, + {text: 'OK', onPress: () => console.log('OK Pressed')}, ], { cancelable: false } )Methods #
static alert(title, message?, buttons?, options?, type?) #
You can edit the content above on GitHub and send us a pull request!
AlertIOS #
AlertIOSprovides functionality to create an iOS alert dialog with a -message or create a prompt for user input.Creating an iOS alert:
AlertIOS.alert( +AlertIOS AlertIOS #
AlertIOSprovides functionality to create an iOS alert dialog with a +message or create a prompt for user input.Creating an iOS alert:
AlertIOS.alert( 'Sync Complete', 'All your data are belong to us.' -);Creating an iOS prompt:
AlertIOS.prompt( +);Creating an iOS prompt:
AlertIOS.prompt( 'Enter a value', null, - text => console.log("You entered "+text) + text => console.log("You entered "+text) );We recommend using the
Alert.alertmethod for cross-platform support if you don't need to create iOS-only prompts.Methods #
static alert(title: string, message?: string, callbackOrButtons?: ?(() => void), ButtonsArray, type?: AlertType) #
Create and display a popup alert.
Parameters:Name and Type Description title stringThe dialog's title.
[message] stringAn optional message that appears below the dialog's title.
[callbackOrButtons] ?(() => void) | ButtonsArrayThis optional argument should be either a single-argument function or an array of buttons. If passed a function, it will be called when the user taps 'OK'.
If passed an array of button configurations, each button should include a
textkey, as well as optionalonPressandstylekeys.style- should be one of 'default', 'cancel' or 'destructive'.[type] Deprecated, do not use.
Example with custom buttons:AlertIOS.alert( + should be one of 'default', 'cancel' or 'destructive'.[type] Deprecated, do not use.
Example with custom buttons:AlertIOS.alert( 'Update available', 'Keep your app up to date to enjoy the latest features', [ - {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, - {text: 'Install', onPress: () => console.log('Install Pressed')}, + {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, + {text: 'Install', onPress: () => console.log('Install Pressed')}, ], );static prompt(title: string, message?: string, callbackOrButtons?: ?((text: string) => void), ButtonsArray, type?: AlertType, defaultValue?: string, keyboardType?: string) #
Create and display a prompt to enter some text.
Parameters:Name and Type Description title stringThe dialog's title.
[message] stringAn optional message that appears above the text input.
[callbackOrButtons] ?((text: string) => void) | ButtonsArrayThis optional argument should @@ -29,18 +29,18 @@ cross-platform support if you don't need to create iOS-only prompts.
[defaultValue] stringThe default text in text input.
[keyboardType] stringThe keyboard type of first text field(if exists). One of 'default', 'email-address', 'numeric', 'phone-pad', 'ascii-capable', 'numbers-and-punctuation', 'url', 'number-pad', - 'name-phone-pad', 'decimal-pad', 'twitter' or 'web-search'.
Example with custom buttons:AlertIOS.prompt( + 'name-phone-pad', 'decimal-pad', 'twitter' or 'web-search'.
Example with custom buttons:AlertIOS.prompt( 'Enter password', 'Enter your password to claim your $1.5B in lottery winnings', [ - {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, - {text: 'OK', onPress: password => console.log('OK Pressed, password: ' + password)}, + {text: 'Cancel', onPress: () => console.log('Cancel Pressed'), style: 'cancel'}, + {text: 'OK', onPress: password => console.log('OK Pressed, password: ' + password)}, ], 'secure-text' -);
Example with the default button and a custom callback:AlertIOS.prompt( +);
Example with the default button and a custom callback:AlertIOS.prompt( 'Update username', null, - text => console.log("Your username is "+text), + text => console.log("Your username is "+text), null, 'default' );Type Definitions #
AlertType #
Type:An Alert button type
$Enum
Constants:Value Description default Default alert with no inputs
plain-text Plain text input alert
secure-text Secure text input alert
login-password Login and password alert
AlertButtonStyle #
Type:An Alert button style
$Enum
Constants:Value Description default Default button style
cancel Cancel button style
destructive Destructive button style
ButtonsArray #
Type:Array or buttons
Array
Properties:Name and Type Description [text] stringButton label
[onPress] functionCallback function when button pressed
[style] Button style
Constants:Value Description text Button label
onPress Callback function when button pressed
style Button style
You can edit the content above on GitHub and send us a pull request!
Building React Native from source #
You will need to build React Native from source if you want to work on a new feature/bug fix, try out the latest features which are not released yet, or maintain your own fork with patches that cannot be merged to the core.
Prerequisites #
Assuming you have the Android SDK installed, run
androidto open the Android SDK Manager.Make sure you have the following installed:
- Android SDK version 23 (compileSdkVersion in
build.gradle) - SDK build tools version 23.0.1 (buildToolsVersion in
build.gradle) - Android Support Repository >= 17 (for Android Support Library)
- Android NDK (download links and installation instructions below)
Point Gradle to your Android SDK: #
Step 1: Set environment variables through your local shell.
Note: Files may vary based on shell flavor. See below for examples from common shells.
- bash:
.bash_profileor.bashrc - zsh:
.zprofileor.zshrc - ksh:
.profileor$ENV
Example:
export ANDROID_SDK=/Users/your_unix_name/android-sdk-macosx -export ANDROID_NDK=/Users/your_unix_name/android-ndk/android-ndk-r10eStep 2: Create a
local.propertiesfile in theandroiddirectory of your react-native app with the following contents:Example:
sdk.dir=/Users/your_unix_name/android-sdk-macosx -ndk.dir=/Users/your_unix_name/android-ndk/android-ndk-r10eDownload links for Android NDK #
- Mac OS (64-bit) - http://dl.google.com/android/repository/android-ndk-r10e-darwin-x86_64.zip
- Linux (64-bit) - http://dl.google.com/android/repository/android-ndk-r10e-linux-x86_64.zip
- Windows (64-bit) - http://dl.google.com/android/repository/android-ndk-r10e-windows-x86_64.zip
- Windows (32-bit) - http://dl.google.com/android/repository/android-ndk-r10e-windows-x86.zip
You can find further instructions on the official page.
Building the source #
1. Installing the fork #
First, you need to install
react-nativefrom your fork. For example, to install the master branch from the official repo, run the following:npm install --save github:facebook/react-native#masterAlternatively, you can clone the repo to your
node_modulesdirectory and runnpm installinside the cloned repo.2. Adding gradle dependencies #
Add
gradle-download-taskas dependency inandroid/build.gradle:... +Building React Native from source Building React Native from source #
You will need to build React Native from source if you want to work on a new feature/bug fix, try out the latest features which are not released yet, or maintain your own fork with patches that cannot be merged to the core.
Prerequisites #
Assuming you have the Android SDK installed, run
androidto open the Android SDK Manager.Make sure you have the following installed:
- Android SDK version 23 (compileSdkVersion in
build.gradle) - SDK build tools version 23.0.1 (buildToolsVersion in
build.gradle) - Android Support Repository >= 17 (for Android Support Library)
- Android NDK (download links and installation instructions below)
Point Gradle to your Android SDK: #
Step 1: Set environment variables through your local shell.
Note: Files may vary based on shell flavor. See below for examples from common shells.
- bash:
.bash_profileor.bashrc - zsh:
.zprofileor.zshrc - ksh:
.profileor$ENV
Example:
export ANDROID_SDK=/Users/your_unix_name/android-sdk-macosx +export ANDROID_NDK=/Users/your_unix_name/android-ndk/android-ndk-r10eStep 2: Create a
local.propertiesfile in theandroiddirectory of your react-native app with the following contents:Example:
sdk.dir=/Users/your_unix_name/android-sdk-macosx +ndk.dir=/Users/your_unix_name/android-ndk/android-ndk-r10eDownload links for Android NDK #
- Mac OS (64-bit) - http://dl.google.com/android/repository/android-ndk-r10e-darwin-x86_64.zip
- Linux (64-bit) - http://dl.google.com/android/repository/android-ndk-r10e-linux-x86_64.zip
- Windows (64-bit) - http://dl.google.com/android/repository/android-ndk-r10e-windows-x86_64.zip
- Windows (32-bit) - http://dl.google.com/android/repository/android-ndk-r10e-windows-x86.zip
You can find further instructions on the official page.
Building the source #
1. Installing the fork #
First, you need to install
react-nativefrom your fork. For example, to install the master branch from the official repo, run the following:npm install --save github:facebook/react-native#masterAlternatively, you can clone the repo to your
node_modulesdirectory and runnpm installinside the cloned repo.2. Adding gradle dependencies #
Add
gradle-download-taskas dependency inandroid/build.gradle:... dependencies { classpath 'com.android.tools.build:gradle:1.3.1' classpath 'de.undercouch:gradle-download-task:3.1.2' @@ -8,23 +8,23 @@ ndk.dir= // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } -...3. Adding the
:ReactAndroidproject #Add the
:ReactAndroidproject inandroid/settings.gradle:... +...3. Adding the
:ReactAndroidproject #Add the
:ReactAndroidproject inandroid/settings.gradle:... include ':ReactAndroid' -project(':ReactAndroid').projectDir = new File( +project(':ReactAndroid').projectDir = new File( rootProject.projectDir, '../node_modules/react-native/ReactAndroid') -...Modify your
android/app/build.gradleto use the:ReactAndroidproject instead of the pre-compiled library, e.g. - replacecompile 'com.facebook.react:react-native:+'withcompile project(':ReactAndroid'):... +...Modify your
android/app/build.gradleto use the:ReactAndroidproject instead of the pre-compiled library, e.g. - replacecompile 'com.facebook.react:react-native:+'withcompile project(':ReactAndroid'):... dependencies { - compile fileTree(dir: 'libs', include: ['*.jar']) + compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:23.0.1' - compile project(':ReactAndroid') + compile project(':ReactAndroid') - ... + ... } -...4. Making 3rd-party modules use your fork #
If you use 3rd-party React Native modules, you need to override their dependencies so that they don't bundle the pre-compiled library. Otherwise you'll get an error while compiling -
Error: more than one library with package name 'com.facebook.react'.Modify your
android/app/build.gradle, and add:configurations.all { +...4. Making 3rd-party modules use your fork #
If you use 3rd-party React Native modules, you need to override their dependencies so that they don't bundle the pre-compiled library. Otherwise you'll get an error while compiling -
Error: more than one library with package name 'com.facebook.react'.Modify your
android/app/build.gradle, and add:configurations.all { exclude group: 'com.facebook.react', module: 'react-native' -}Building from Android Studio #
From the Welcome screen of Android Studio choose "Import project" and select the
androidfolder of your app.You should be able to use the Run button to run your app on a device. Android Studio won't start the packager automatically, you'll need to start it by running
npm starton the command line.Additional notes #
Building from source can take a long time, especially for the first build, as it needs to download ~200 MB of artifacts and compile the native code. Every time you update the
react-nativeversion from your repo, the build directory may get deleted, and all the files are re-downloaded. To avoid this, you might want to change your build directory path by editing the~/.gradle/init.gradlefile:gradle.projectsLoaded { +}Building from Android Studio #
From the Welcome screen of Android Studio choose "Import project" and select the
androidfolder of your app.You should be able to use the Run button to run your app on a device. Android Studio won't start the packager automatically, you'll need to start it by running
npm starton the command line.Additional notes #
Building from source can take a long time, especially for the first build, as it needs to download ~200 MB of artifacts and compile the native code. Every time you update the
react-nativeversion from your repo, the build directory may get deleted, and all the files are re-downloaded. To avoid this, you might want to change your build directory path by editing the~/.gradle/init.gradlefile:gradle.projectsLoaded { rootProject.allprojects { buildDir = "/path/to/build/directory/${rootProject.name}/${project.name}" } diff --git a/releases/next/docs/animated.html b/releases/next/docs/animated.html index 9a86ab921bf..fb0e081be39 100644 --- a/releases/next/docs/animated.html +++ b/releases/next/docs/animated.html @@ -1,14 +1,14 @@ -Animated Animated #
The
Animatedlibrary is designed to make animations fluid, powerful, and +Animated Animated #
The
Animatedlibrary is designed to make animations fluid, powerful, and easy to build and maintain.Animatedfocuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simplestart/stopmethods to control time-based animation execution.The simplest workflow for creating an animation is to to create an
Animated.Value, hook it up to one or more style attributes of an animated -component, and then drive updates via animations usingAnimated.timing():Animated.timing( // Animate value over time +component, and then drive updates via animations usingAnimated.timing():Animated.timing( // Animate value over time this.state.fadeAnim, // The value to drive { toValue: 1, // Animate to final value of 1 } -).start(); // Start the animationRefer to the Animations guide to see +).start(); // Start the animation
Refer to the Animations guide to see additional examples of
Animatedin action.Overview #
There are two value types you can use with
Animated:Animated.Value()for single valuesAnimated.ValueXY()for vectors
Animated.Valuecan bind to style properties or other props, and can be interpolated as well. A singleAnimated.Valuecan drive any number of properties.Configuring animations #
Animatedprovides three types of animation types. Each animation type @@ -55,7 +55,7 @@ syntax so that values can be extracted from complex event objects. The first level is an array to allow mapping across multiple args, and that array contains nested objects.For example, when working with horizontal scrolling gestures, you would do the following in order to map
event.nativeEvent.contentOffset.xto -scrollX(anAnimated.Value):onScroll={Animated.event( +scrollX(anAnimated.Value):onScroll={Animated.event( // scrollX = e.nativeEvent.contentOffset.x [{ nativeEvent: { contentOffset: { @@ -69,7 +69,8 @@ coefficient.Config is an object that may have the following options:
< can use your own function.Config is an object that may have the following options:
duration: Length of animation (milliseconds). Default 500.easing: Easing function to define curve. Default isEasing.inOut(Easing.ease).delay: Start the animation after delay (milliseconds). Default 0.useNativeDriver: Uses the native driver when true. Default false.
static spring(value, config) #
Spring animation based on Rebound and Origami. Tracks velocity state to -create fluid motions as the
toValueupdates, and can be chained together.Config is an object that may have the following options:
friction: Controls "bounciness"/overshoot. Default 7.tension: Controls speed. Default 40.useNativeDriver: Uses the native driver when true. Default false.
static add(a, b) #
Creates a new Animated value composed from two Animated values added +create fluid motions as the
toValueupdates, and can be chained together.Config is an object that may have the following options. Note that you can +only define bounciness/speed or tension/friction but not both:
friction: Controls "bounciness"/overshoot. Default 7.tension: Controls speed. Default 40.speed: Controls speed of the animation. Default 12.bounciness: Controls bounciness. Default 8.useNativeDriver: Uses the native driver when true. Default false.
static add(a, b) #
Creates a new Animated value composed from two Animated values added together.
static divide(a, b) #
Creates a new Animated value composed by dividing the first Animated value by the second Animated value.
static multiply(a, b) #
Creates a new Animated value composed from two Animated values multiplied together.
static modulo(a, modulus) #
Creates a new Animated value that is the (non-negative) modulo of the @@ -86,12 +87,12 @@ sequence with successive delays. Nice for doing trailing effects.
static event(argMapping, config?) #
Takes an array of mappings and extracts values from each arg accordingly, -then calls
setValueon the mapped outputs. e.g.onScroll={Animated.event( +then callssetValueon the mapped outputs. e.g.onScroll={Animated.event( [{nativeEvent: {contentOffset: {x: this._scrollX}}}] {listener}, // Optional async listener ) - ... - onPanResponderMove: Animated.event([ + ... + onPanResponderMove: Animated.event([ null, // raw event arg ignored {dx: this._panX}, // gestureState arg ]),Config is an object that may have the following options:
listener: Optional async listener.useNativeDriver: Uses the native driver when true. Default false.
static createAnimatedComponent(Component) #
Make any React component Animatable. Used to create
Animated.View, etc.static attachNativeEvent(viewRef, eventName, argMapping) #
Imperative API to attach an animated value to an event on a view. Prefer using @@ -113,37 +114,37 @@ state to match the animation position with layout.
animate(animation, callback) #
Typically only used internally, but could be used by a custom Animation class.
stopTracking() #
Typically only used internally.
track(tracking) #
Typically only used internally.
class AnimatedValueXY #
2D Value for driving 2D animations, such as pan gestures. Almost identical API to normal
Animated.Value, but multiplexed. Contains two regular -Animated.Values under the hood.Example #
class DraggableView extends React.Component { - constructor(props) { - super(props); +Animated.Values under the hood.Example #
class DraggableView extends React.Component { + constructor(props) { + super(props); this.state = { pan: new Animated.ValueXY(), // inits to zero }; - this.state.panResponder = PanResponder.create({ - onStartShouldSetPanResponder: () => true, - onPanResponderMove: Animated.event([null, { + this.state.panResponder = PanResponder.create({ + onStartShouldSetPanResponder: () => true, + onPanResponderMove: Animated.event([null, { dx: this.state.pan.x, // x,y are Animated.Value dy: this.state.pan.y, }]), - onPanResponderRelease: () => { - Animated.spring( + onPanResponderRelease: () => { + Animated.spring( this.state.pan, // Auto-multiplexed {toValue: {x: 0, y: 0}} // Back to zero - ).start(); + ).start(); }, }); } - render() { + render() { return ( - <Animated.View - {...this.state.panResponder.panHandlers} - style={this.state.pan.getLayout()}> + <Animated.View + {...this.state.panResponder.panHandlers} + style={this.state.pan.getLayout()}> {this.props.children} - </Animated.View> + </Animated.View> ); } - }Methods #
constructor(valueIn?) #
setValue(value) #
setOffset(offset) #
flattenOffset() #
extractOffset() #
resetAnimation(callback?) #
stopAnimation(callback?) #
addListener(callback) #
removeListener(id) #
removeAllListeners() #
getLayout() #
Converts
{x, y}into{left, top}for use in style, e.g.style={this.state.anim.getLayout()}getTranslateTransform() #
Converts
{x, y}into a useable translation transform, e.g.style={{ - transform: this.state.anim.getTranslateTransform() + }Methods #
constructor(valueIn?) #
setValue(value) #
setOffset(offset) #
flattenOffset() #
extractOffset() #
resetAnimation(callback?) #
stopAnimation(callback?) #
addListener(callback) #
removeListener(id) #
removeAllListeners() #
getLayout() #
Converts
{x, y}into{left, top}for use in style, e.g.style={this.state.anim.getLayout()}getTranslateTransform() #
Converts
{x, y}into a useable translation transform, e.g.style={{ + transform: this.state.anim.getTranslateTransform() }}class AnimatedInterpolation #
Methods #
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:
Animatedfor granular and interactive control of specific values, andLayoutAnimationfor animated global layout transactions.AnimatedAPI #The
AnimatedAPI is designed to make it very easy to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. -Animatedfocuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simplestart/stopmethods to control time-based animation execution.Animatedexports four animatable component types:View,Text,Image, andScrollView, but you can also create your own usingAnimated.createAnimatedComponent().For example, a container view that fades in when it is mounted may look like this:
- Scroll loading (
React Native