diff --git a/docs/accessibility.html b/docs/accessibility.html index 888ad72b03c..57836b28e4d 100644 --- a/docs/accessibility.html +++ b/docs/accessibility.html @@ -1,23 +1,23 @@ -
Accessibility # | Edit on GitHub |
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.
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}’.
Accessibility # | Edit on GitHub |
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.
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}’.
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.
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 accessibilityLabel property to a custom string on your 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.
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 accessibilityLabel property to a custom string on your View:
In the above example, the accessibilityLabel on the TouchableOpacity element would default to "Press me!". The label is constructed by concatenating all Text node children separated by spaces.
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 accessibilityTraits property to one of (or an array of) accessibility trait strings:
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.
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 onMagicTap function, the system will traverse up the view hierarchy until it finds a view that does.
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.
In the above example, the accessibilityLabel on the TouchableOpacity element would default to "Press me!". The label is constructed by concatenating all Text node children separated by spaces.
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 accessibilityTraits property to one of (or an array of) accessibility trait strings:
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.
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 onMagicTap function, the system will traverse up the view hierarchy until it finds a view that does.
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.
In the above example, the TouchableWithoutFeedback is being announced by TalkBack as a native Button.
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’:
In the above example, the TouchableWithoutFeedback is being announced by TalkBack as a native Button.
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’:
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.
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).
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.
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).
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.
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.
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.
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.
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.
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 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.
ActionSheetIOS # | Edit on GitHub |
Examples # | Edit on GitHub |
ActionSheetIOS # | Edit on GitHub |
Examples # | Edit on GitHub |
ActivityIndicatorIOS # | Edit on GitHub |
Whether to show the indicator (true, the default) or hide it (false).
The foreground color of the spinner (default is gray).
Whether the indicator should hide when not animating (true by default).
Invoked on mount and layout changes with
{nativeEvent: { layout: {x, y, width, height}}}.
Size of the indicator. Small has a height of 20, large has a height of 36.
Examples # | Edit on GitHub |
ActivityIndicatorIOS # | Edit on GitHub |
Whether to show the indicator (true, the default) or hide it (false).
The foreground color of the spinner (default is gray).
Whether the indicator should hide when not animating (true by default).
Invoked on mount and layout changes with
{nativeEvent: { layout: {x, y, width, height}}}.
Size of the indicator. Small has a height of 20, large has a height of 36.
Examples # | Edit on GitHub |
Alert # | Edit on GitHub |
Launches an alert dialog with the specified title and message.
Optionally provide a list of buttons. Tapping any button will fire the +
Alert # | Edit on GitHub |
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,
-see AlertIOS; entering text in an alert is common on iOS only.
On iOS you can specify any number of buttons. Each button can optionally -specify a style, which is one of 'default', 'cancel' or 'destructive'.
On Android at most three buttons can be specified. Android has a concept
+see AlertIOS; entering text in an alert is common on iOS only.
On iOS you can specify any number of buttons. Each button can optionally +specify a style, which is one of 'default', 'cancel' or 'destructive'.
On Android at most three buttons can be specified. Android has a concept of a neutral, negative and a positive button:
Examples # | Edit on GitHub |
Examples # | Edit on GitHub |
AlertIOS # | Edit on GitHub |
The AlertsIOS utility provides two functions: alert and prompt. All
+
AlertIOS # | Edit on GitHub |
The AlertsIOS utility provides two functions: alert and prompt. All
functionality available through AlertIOS.alert is also available in the
cross-platform Alert.alert, which we recommend you use if you don't need
iOS-specific functionality.
AlertIOS.prompt allows you to prompt the user for input inside of an
-alert popup.
Creates a popup to alert the user. See +alert popup.
Creates a popup to alert the user. See Alert.
callbackOrButtons -- This 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
@@ -10,7 +10,7 @@ a text key, as well as optional onPress and styl
style should be one of 'default', 'cancel' or 'destructive'.
Example:
Prompt the user to enter some text.
callbackOrButtons -- This optional argument should be either a +);
Prompt the user to enter some text.
callbackOrButtons -- This optional argument should be either a single-argument function or an array of buttons. If passed a function, it will be called with the prompt's value when the user taps 'OK'.
If passed an array of button configurations, each button should include
a text key, as well as optional onPress and style keys (see example).
@@ -29,7 +29,7 @@ a text key, as well as optional onPress and styl
text => console.log("Your username is "+text),
null,
'default'
-)
Examples # | Edit on GitHub |
Examples # | Edit on GitHub |
Building React Native from source # | Edit on GitHub |
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.
Assuming you have the Android SDK installed, run android to open the Android SDK Manager.
Make sure you have the following installed:
build.gradle)build.gradle)Point Gradle to your Android SDK: either have $ANDROID_SDK and $ANDROID_NDK defined, or create a local.properties file in the root of your react-native checkout with the following contents:
Building React Native from source # | Edit on GitHub |
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.
Assuming you have the Android SDK installed, run android to open the Android SDK Manager.
Make sure you have the following installed:
build.gradle)build.gradle)Point Gradle to your Android SDK: either have $ANDROID_SDK and $ANDROID_NDK defined, or create a local.properties file in the root of your react-native checkout with the following contents:
Example:
First, you need to install react-native from your fork. For example, to install the master branch from the official repo, run the following:
Alternatively, you can clone the repo to your node_modules directory and run npm install inside the cloned repo.
Add gradle-download-task as dependency in android/build.gradle:
First, you need to install react-native from your fork. For example, to install the master branch from the official repo, run the following:
Alternatively, you can clone the repo to your node_modules directory and run npm install inside the cloned repo.
Add gradle-download-task as dependency in android/build.gradle:
:ReactAndroid project #Add the :ReactAndroid project in android/settings.gradle:
:ReactAndroid project #Add the :ReactAndroid project in android/settings.gradle:
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 replace compile project(':react-native-custom-module') with:
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 replace compile project(':react-native-custom-module') with:
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-native version 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.gradle file:
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-native version 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.gradle file:
Android Setup # | Edit on GitHub |
This guide describes basic steps of the Android development environment setup that are required to run React Native android apps on an android emulator. We don't discuss developer tool configuration such as IDEs here.
On Mac, if you have installed XCode, Git is already installed, otherwise run the following:
On Linux, install Git via your package manager.
On Windows, download and install Git for Windows. During the setup process, choose "Run Git from Windows Command Prompt", which will add Git to your PATH environment variable.
brew install android-sdkIMPORTANT: Make sure the ANDROID_HOME environment variable points to your existing Android SDK:
On Mac, add this to your ~/.bashrc, ~/.bash_profile or whatever your shell uses:
On Linux, add this to your ~/.bashrc, ~/.bash_profile or whatever your shell uses:
On Windows, go to Control Panel -> System and Security -> System -> Change settings -> Advanced -> Environment variables -> New
NOTE: You need to restart the Command Prompt (Windows) / Terminal Emulator (Mac OS X, Linux) to apply the new Environment variables.
React Native Android use gradle as a build system. We recommend to enable gradle daemon functionality which may result in up to 50% improvement in incremental build times for changes in java code. Learn here how to enable it for your platform.
android); in the window that appears make sure you check:

Genymotion is much easier to set up than stock Google emulators. However, it's only free for personal use. If you want to use the stock Google emulator, see below.
android; in the window that appears make sure you check:android avd and click on Create...
-
Start...The Visual Studio Emulator for Android is a free android emulator that is hardware accelerated via Hyper-V. It doesn't require you to install Visual Studio at all.
To use it with react-native you just have to add a key and value to your registry:
regedit.exeHKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Android SDK ToolsAndroid SDK Tools and choose New > String ValuePathPath Key and set the value to C:\Program Files\Android\sdk. The path value might be different on your machine.You will also need to run the command adb reverse tcp:8081 tcp:8081 with this emulator.
Then restart the emulator and when it runs you can just do react-native run-android as usual.
Android Setup # | Edit on GitHub |
This guide describes basic steps of the Android development environment setup that are required to run React Native android apps on an android emulator.
On Mac, if you have installed XCode, Git is already installed, otherwise run the following:
On Linux, install Git via your package manager.
On Windows, download and install Git for Windows. During the setup process, choose "Run Git from Windows Command Prompt", which will add Git to your PATH environment variable.
brew install android-sdkIMPORTANT: Make sure the ANDROID_HOME environment variable points to your existing Android SDK:
On Mac, add this to your ~/.bashrc, ~/.bash_profile or whatever your shell uses:
On Linux, add this to your ~/.bashrc, ~/.bash_profile or whatever your shell uses:
On Windows, go to Control Panel -> System and Security -> System -> Change settings -> Advanced -> Environment variables -> New
NOTE: You need to restart the Command Prompt (Windows) / Terminal Emulator (Mac OS X, Linux) to apply the new Environment variables.
React Native Android use gradle as a build system. We recommend to enable gradle daemon functionality which may result in up to 50% improvement in incremental build times for changes in java code. Learn here how to enable it for your platform.
android); in the window that appears make sure you check:

Genymotion is much easier to set up than stock Google emulators. However, it's only free for personal use. If you want to use the stock Google emulator, see below.
android; in the window that appears make sure you check:android avd and click on Create...
+
Start...The Visual Studio Emulator for Android is a free android emulator that is hardware accelerated via Hyper-V. It doesn't require you to install Visual Studio at all.
To use it with react-native you just have to add a key and value to your registry:
regedit.exeHKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Android SDK ToolsAndroid SDK Tools and choose New > String ValuePathPath Key and set the value to C:\Program Files\Android\sdk. The path value might be different on your machine.You will also need to run the command adb reverse tcp:8081 tcp:8081 with this emulator.
Then restart the emulator and when it runs you can just do react-native run-android as usual.
You can use any editor to edit JavaScript. If you want to use Android Studio to work on native code, from the Welcome screen of Android Studio choose "Import project" and select the android folder of your app.
Profiling Android UI Performance # | Edit on GitHub |
We try our best to deliver buttery-smooth UI performance by default, but sometimes that just isn't possible. Remember, Android supports 10k+ different phones and is generalized to support software rendering: the framework architecture and need to generalize across many hardware targets unfortunately means you get less for free relative to iOS. But sometimes, there are things you can improve (and many times it's not native code's fault at all!).
The first step for debugging this jank is to answer the fundamental question of where your time is being spent during each 16ms frame. For that, we'll be using a standard Android profiling tool called systrace. But first...
Make sure that JS dev mode is OFF!
You should see
__DEV__ === false, development-level warning are OFF, performance optimizations are ONin your application logs (which you can view usingadb logcat)
Systrace is a standard Android marker-based profiling tool (and is installed when you install the Android platform-tools package). Profiled code blocks are surrounded by markers start/end markers which are then visualized in a colorful chart format. Both the Android SDK and React Native framework provide standard markers that you can visualize.
NOTE:
Systrace support was added in react-native
v0.15. You will need to build with that version to collect a trace.
First, connect a device that exhibits the stuttering you want to investigate to your computer via USB and get it to the point right before the navigation/animation you want to profile. Run systrace as follows
A quick breakdown of this command:
time is the length of time the trace will be collected in secondssched, gfx, and view are the android SDK tags (collections of markers) we care about: sched gives you information about what's running on each core of your phone, gfx gives you graphics info such as frame boundaries, and view gives you information about measure, layout, and draw passes-a <your_package_name> enables app-specific markers, specifically the ones built into the React Native framework. your_package_name can be found in the AndroidManifest.xml of your app and looks like com.example.appOnce the trace starts collecting, perform the animation or interaction you care about. At the end of the trace, systrace will give you a link to the trace which you can open in your browser.
After opening the trace in your browser (preferably Chrome), you should see something like this:

HINT: Use the WASD keys to strafe and zoom
The first thing you should do is highlight the 16ms frame boundaries if you haven't already done that. Check this checkbox at the top right of the screen:

You should see zebra stripes as in the screenshot above. If you don't, try profiling on a different device: Samsung has been known to have issues displaying vsyncs while the Nexus series is generally pretty reliable.
Scroll until you see (part of) the name of your package. In this case, I was profiling com.facebook.adsmanager, which shows up as book.adsmanager because of silly thread name limits in the kernel.
On the left side, you'll see a set of threads which correspond to the timeline rows on the right. There are three/four threads we care about for our purposes: the UI thread (which has your package name or the name UI Thread), mqt_js and mqt_native_modules. If you're running on Android 5+, we also care about the Render Thread.
This is where standard android measure/layout/draw happens. The thread name on the right will be your package name (in my case book.adsmanager) or UI Thread. The events that you see on this thread should look something like this and have to do with Choreographer, traversals, and DispatchUI:

This is where JS is executed. The thread name will be either mqt_js or <...> depending on how cooperative the kernel on your device is being. To identify it if it doesn't have a name, look for things like JSCall, Bridge.executeJSCall, etc:

This is where native module calls (e.g. the UIManager) are executed. The thread name will be either mqt_native_modules or <...>. To identify it in the latter case, look for things like NativeCall, callJavaModuleMethod, and onBatchComplete:

If you're using Android L (5.0) and up, you will also have a render thread in your application. This thread generates the actual OpenGL commands used to draw your UI. The thread name will be either RenderThread or <...>. To identify it in the latter case, look for things like DrawFrame and queueBuffer:

A smooth animation should look something like the following:

Each change in color is a frame -- remember that in order to display a frame, all our UI work needs to be done by the end of that 16ms period. Notice that no thread is working close to the frame boundary. An application rendering like this is rendering at 60FPS.
If you noticed chop, however, you might see something like this:

Notice that the JS thread is executing basically all the time, and across frame boundaries! This app is not rendering at 60FPS. In this case, the problem lies in JS.
You might also see something like this:

In this case, the UI and render threads are the ones that have work crossing frame boundaries. The UI that we're trying to render on each frame is requiring too much work to be done. In this case, the problem lies in the native views being rendered.
At this point, you'll have some very helpful information to inform your next steps.
If you identified a JS problem, look for clues in the specific JS that you're executing. In the scenario above, we see RCTEventEmitter being called multiple times per frame. Here's a zoom-in of the JS thread from the trace above:

This doesn't seem right. Why is it being called so often? Are they actually different events? The answers to these questions will probably depend on your product code. And many times, you'll want to look into shouldComponentUpdate.
TODO: Add more tools for profiling JS
If you identified a native UI problem, there are usually two scenarios:
In the first scenario, you'll see a trace that has the UI thread and/or Render Thread looking like this:

Notice the long amount of time spent in DrawFrame that crosses frame boundaries. This is time spent waiting for the GPU to drain its command buffer from the previous frame.
To mitigate this, you should:
renderToHardwareTextureAndroid for complex, static content that is being animated/transformed (e.g. the Navigator slide/alpha animations)needsOffscreenAlphaCompositing, which is disabled by default, as it greatly increases the per-frame load on the GPU in most cases.If these don't help and you want to dig deeper into what the GPU is actually doing, you can check out Tracer for OpenGL ES.
In the second scenario, you'll see something more like this:

Notice that first the JS thread thinks for a bit, then you see some work done on the native modules thread, followed by an expensive traversal on the UI thread.
There isn't an easy way to mitigate this unless you're able to postpone creating new UI until after the interaction, or you are able to simplify the UI you're creating. The react native team is working on a infrastructure level solution for this that will allow new UI to be created and configured off the main thread, allowing the interaction to continue smoothly.
If you are confused or stuck, please post ask on Stack Overflow with the react-native tag. If you are unable to get a response there, or find an issue with a core component, please File a Github issue.
Profiling Android UI Performance # | Edit on GitHub |
We try our best to deliver buttery-smooth UI performance by default, but sometimes that just isn't possible. Remember, Android supports 10k+ different phones and is generalized to support software rendering: the framework architecture and need to generalize across many hardware targets unfortunately means you get less for free relative to iOS. But sometimes, there are things you can improve (and many times it's not native code's fault at all!).
The first step for debugging this jank is to answer the fundamental question of where your time is being spent during each 16ms frame. For that, we'll be using a standard Android profiling tool called systrace. But first...
Make sure that JS dev mode is OFF!
You should see
__DEV__ === false, development-level warning are OFF, performance optimizations are ONin your application logs (which you can view usingadb logcat)
Systrace is a standard Android marker-based profiling tool (and is installed when you install the Android platform-tools package). Profiled code blocks are surrounded by markers start/end markers which are then visualized in a colorful chart format. Both the Android SDK and React Native framework provide standard markers that you can visualize.
NOTE:
Systrace support was added in react-native
v0.15. You will need to build with that version to collect a trace.
First, connect a device that exhibits the stuttering you want to investigate to your computer via USB and get it to the point right before the navigation/animation you want to profile. Run systrace as follows
A quick breakdown of this command:
time is the length of time the trace will be collected in secondssched, gfx, and view are the android SDK tags (collections of markers) we care about: sched gives you information about what's running on each core of your phone, gfx gives you graphics info such as frame boundaries, and view gives you information about measure, layout, and draw passes-a <your_package_name> enables app-specific markers, specifically the ones built into the React Native framework. your_package_name can be found in the AndroidManifest.xml of your app and looks like com.example.appOnce the trace starts collecting, perform the animation or interaction you care about. At the end of the trace, systrace will give you a link to the trace which you can open in your browser.
After opening the trace in your browser (preferably Chrome), you should see something like this:

HINT: Use the WASD keys to strafe and zoom
The first thing you should do is highlight the 16ms frame boundaries if you haven't already done that. Check this checkbox at the top right of the screen:

You should see zebra stripes as in the screenshot above. If you don't, try profiling on a different device: Samsung has been known to have issues displaying vsyncs while the Nexus series is generally pretty reliable.
Scroll until you see (part of) the name of your package. In this case, I was profiling com.facebook.adsmanager, which shows up as book.adsmanager because of silly thread name limits in the kernel.
On the left side, you'll see a set of threads which correspond to the timeline rows on the right. There are three/four threads we care about for our purposes: the UI thread (which has your package name or the name UI Thread), mqt_js and mqt_native_modules. If you're running on Android 5+, we also care about the Render Thread.
This is where standard android measure/layout/draw happens. The thread name on the right will be your package name (in my case book.adsmanager) or UI Thread. The events that you see on this thread should look something like this and have to do with Choreographer, traversals, and DispatchUI:

This is where JS is executed. The thread name will be either mqt_js or <...> depending on how cooperative the kernel on your device is being. To identify it if it doesn't have a name, look for things like JSCall, Bridge.executeJSCall, etc:

This is where native module calls (e.g. the UIManager) are executed. The thread name will be either mqt_native_modules or <...>. To identify it in the latter case, look for things like NativeCall, callJavaModuleMethod, and onBatchComplete:

If you're using Android L (5.0) and up, you will also have a render thread in your application. This thread generates the actual OpenGL commands used to draw your UI. The thread name will be either RenderThread or <...>. To identify it in the latter case, look for things like DrawFrame and queueBuffer:

A smooth animation should look something like the following:

Each change in color is a frame -- remember that in order to display a frame, all our UI work needs to be done by the end of that 16ms period. Notice that no thread is working close to the frame boundary. An application rendering like this is rendering at 60FPS.
If you noticed chop, however, you might see something like this:

Notice that the JS thread is executing basically all the time, and across frame boundaries! This app is not rendering at 60FPS. In this case, the problem lies in JS.
You might also see something like this:

In this case, the UI and render threads are the ones that have work crossing frame boundaries. The UI that we're trying to render on each frame is requiring too much work to be done. In this case, the problem lies in the native views being rendered.
At this point, you'll have some very helpful information to inform your next steps.
If you identified a JS problem, look for clues in the specific JS that you're executing. In the scenario above, we see RCTEventEmitter being called multiple times per frame. Here's a zoom-in of the JS thread from the trace above:

This doesn't seem right. Why is it being called so often? Are they actually different events? The answers to these questions will probably depend on your product code. And many times, you'll want to look into shouldComponentUpdate.
TODO: Add more tools for profiling JS
If you identified a native UI problem, there are usually two scenarios:
In the first scenario, you'll see a trace that has the UI thread and/or Render Thread looking like this:

Notice the long amount of time spent in DrawFrame that crosses frame boundaries. This is time spent waiting for the GPU to drain its command buffer from the previous frame.
To mitigate this, you should:
renderToHardwareTextureAndroid for complex, static content that is being animated/transformed (e.g. the Navigator slide/alpha animations)needsOffscreenAlphaCompositing, which is disabled by default, as it greatly increases the per-frame load on the GPU in most cases.If these don't help and you want to dig deeper into what the GPU is actually doing, you can check out Tracer for OpenGL ES.
In the second scenario, you'll see something more like this:

Notice that first the JS thread thinks for a bit, then you see some work done on the native modules thread, followed by an expensive traversal on the UI thread.
There isn't an easy way to mitigate this unless you're able to postpone creating new UI until after the interaction, or you are able to simplify the UI you're creating. The react native team is working on a infrastructure level solution for this that will allow new UI to be created and configured off the main thread, allowing the interaction to continue smoothly.
If you are confused or stuck, please post ask on Stack Overflow with the react-native tag. If you are unable to get a response there, or find an issue with a core component, please File a Github issue.
Animated # | Edit on GitHub |
Animations are an important part of modern UX, and the Animated
+
Animated # | Edit on GitHub |
Animations are an important part of modern UX, and the Animated
library is designed to make them fluid, powerful, and easy to build and
maintain.
The simplest workflow is to create an Animated.Value, hook it up to one or
more style attributes of an animated component, and then drive updates either
@@ -58,17 +58,17 @@ event loop. This does influence the API, so keep that in mind when it seems a
little trickier to do something compared to a fully synchronous system.
Checkout Animated.Value.addListener as a way to work around some of these
limitations, but use it sparingly since it might have performance
-implications in the future.
Animates a value from an initial velocity to zero based on a decay -coefficient.
Animates a value along a timed easing curve. The Easing module has tons
-of pre-defined curves, or you can use your own function.
Spring animation based on Rebound and Origami. Tracks velocity state to
-create fluid motions as the toValue updates, and can be chained together.
Creates a new Animated value composed from two Animated values added -together.
Creates a new Animated value composed from two Animated values multiplied -together.
Starts an animation after the given delay.
Starts an array of animations in order, waiting for each to complete +implications in the future.
Animates a value from an initial velocity to zero based on a decay +coefficient.
Animates a value along a timed easing curve. The Easing module has tons
+of pre-defined curves, or you can use your own function.
Spring animation based on Rebound and Origami. Tracks velocity state to
+create fluid motions as the toValue updates, and can be chained together.
Creates a new Animated value composed from two Animated values added +together.
Creates a new Animated value composed from two Animated values multiplied +together.
Starts an animation after the given delay.
Starts an array of animations in order, waiting for each to complete before starting the next. If the current running animation is stopped, no -following animations will be started.
Starts an array of animations all at the same time. By default, if one +following animations will be started.
Starts an array of animations all at the same time. By default, if one
of the animations is stopped, they will all be stopped. You can override
-this with the stopTogether flag.
Array of animations may run in parallel (overlap), but are started in -sequence with successive delays. Nice for doing trailing effects.
Takes an array of mappings and extracts values from each arg accordingly,
+this with the stopTogether flag.
Array of animations may run in parallel (overlap), but are started in +sequence with successive delays. Nice for doing trailing effects.
Takes an array of mappings and extracts values from each arg accordingly,
then calls setValue on the mapped outputs. e.g.
Make any React component Animatable. Used to create Animated.View, etc.
Standard value for driving animations. One Animated.Value can drive
+ ]),
Make any React component Animatable. Used to create Animated.View, etc.
Standard value for driving animations. One Animated.Value can drive
multiple properties in a synchronized fashion, but can only be driven by one
mechanism at a time. Using a new mechanism (e.g. starting a new animation,
-or calling setValue) will stop any previous ones.
Directly set the value. This will stop any animations running on the value -and update all the bound properties.
Sets an offset that is applied on top of whatever value is set, whether via
+or calling setValue) will stop any previous ones.
Directly set the value. This will stop any animations running on the value +and update all the bound properties.
Sets an offset that is applied on top of whatever value is set, whether via
setValue, an animation, or Animated.event. Useful for compensating
-things like the start of a pan gesture.
Merges the offset value into the base value and resets the offset to zero. -The final output of the value is unchanged.
Adds an asynchronous listener to the value so you can observe updates from +things like the start of a pan gesture.
Merges the offset value into the base value and resets the offset to zero. +The final output of the value is unchanged.
Adds an asynchronous listener to the value so you can observe updates from animations. This is useful because there is no way to -synchronously read the value because it might be driven natively.
Stops any running animation or tracking. callback is invoked with the
+synchronously read the value because it might be driven natively.
Stops any running animation or tracking. callback is invoked with the
final value after stopping the animation, which is useful for updating
-state to match the animation position with layout.
Interpolates the value before updating the property, e.g. mapping 0-1 to -0-10.
Typically only used internally, but could be used by a custom Animation -class.
Typically only used internally.
Typically only used internally.
2D Value for driving 2D animations, such as pan gestures. Almost identical +state to match the animation position with layout.
Interpolates the value before updating the property, e.g. mapping 0-1 to +0-10.
Typically only used internally, but could be used by a custom Animation +class.
Typically only used internally.
Typically only used internally.
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:
Animated.Value, but multiplexed. Contains two regula
</Animated.View>
);
}
- }Converts {x, y} into {left, top} for use in style, e.g.
Converts {x, y} into a useable translation transform, e.g.
Converts {x, y} into {left, top} for use in style, e.g.
Converts {x, y} into a useable translation transform, e.g.
Examples # | Edit on GitHub |
Examples # | Edit on GitHub |
Animations # | Edit on GitHub |
Fluid, meaningful animations are essential to the mobile user experience. Like +
Animations # | Edit on GitHub |
Fluid, meaningful animations are essential to the mobile user experience. Like
everything in React Native, Animation APIs for React Native are currently under
development, but have started to coalesce around two complementary systems:
LayoutAnimation for animated global layout transactions, and Animated for
-more granular and interactive control of specific values.
The Animated library is designed to make it very easy to concisely express a
+more granular and interactive control of specific values.
The Animated library is designed to make it very easy to concisely express a
wide variety of interesting animation and interaction patterns in a very
performant way. Animated focuses on declarative relationships between inputs
and outputs, with configurable transforms in between, and simple start/stop
@@ -45,7 +45,7 @@ all of its dependent mappings on each frame as the spring animates (in this
case, just the scale). This is done in an optimized way that is faster than
calling setState and re-rendering. Because the entire configuration is
declarative, we will be able to implement further optimizations that serialize
-the configuration and runs the animation on a high-priority thread.
Most everything you need hangs directly off the Animated module. This
+the configuration and runs the animation on a high-priority thread.
Most everything you need hangs directly off the Animated module. This
includes two value types, Value for single values and ValueXY for vectors,
three animation types, spring, decay, and timing, and three component
types, View, Text, and Image. You can make any other component animated with
@@ -56,7 +56,7 @@ that will be called when the animation is done. If the animation is done
because it finished running normally, the completion callback will be invoked
with {finished: true}, but if the animation is done because stop was called
on it before it could finish (e.g. because it was interrupted by a gesture or
-another animation), then it will receive {finished: false}.
Animations can also be composed with parallel, sequence, stagger, and
+another animation), then it will receive {finished: false}.
Animations can also be composed with parallel, sequence, stagger, and
delay, each of which simply take an array of animations to execute and
automatically calls start/stop as appropriate. For example:
By default, if one animation is stopped or interrupted, then all other
animations in the group are also stopped. Parallel has a stopTogether option
-that can be set to false to disable this.
Another powerful part of the Animated API is the interpolate function. It
+that can be set to false to disable this.
Another powerful part of the Animated API is the interpolate function. It
allows input ranges to map to different output ranges. For example, a simple
mapping to convert a 0-1 range to a 0-100 range would be
interpolation also has configurable behavior
extrapolating the outputRange. You can set the extrapolation by setting the extrapolate,
extrapolateLeft or extrapolateRight options. The default value is
extend but you can use clamp to prevent the output value from exceeding
-outputRange.Animated values can also track other values. Just set the toValue of an
+outputRange.
Animated values can also track other values. Just set the toValue of an
animation to another animated value instead of a plain number, for example with
spring physics for an interaction like "Chat Heads", or via timing with
duration: 0 for rigid/instant tracking. They can also be composed with
@@ -108,7 +108,7 @@ It is a simple wrapper that basically just contains two Animated.ValueValueXY
a drop-in replacement for Value in many cases. For example, in the code
snippet above, leader and follower could both be of type ValueXY and the x
-and y values will both track as you would expect.
Animated.event is the input side of the Animated API, allowing gestures and
+and y values will both track as you would expect.
Animated.event is the input side of the Animated API, allowing gestures and
other events to map directly to animated values. This is done with a structured
map 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
@@ -124,7 +124,7 @@ onPanResponderMove= // extract dx and dy from gestureState
// like 'pan.x = gestureState.dx, pan.y = gestureState.dy'
{dx: pan.x, dy: pan.y}
-]);
You may notice that there is no obvious way to read the current value while +]);
You may notice that there is no obvious way to read the current value while animating - this is because the value may only be known in the native runtime due to optimizations. If you need to run JavaScript in response to the current value, there are two approaches:
spring.stopAnimation(callback) will stop the animation and invoke callback
@@ -132,14 +132,14 @@ with the final value - this is useful when making gesture transitions.As previously mentioned, we're planning on optimizing Animated under the hood to +of lag compared to continuous gestures like panning which need to run at 60fps.
As previously mentioned, we're planning on optimizing Animated under the hood to make it even more performant. We would also like to experiment with more declarative and higher level gestures and triggers, such as horizontal vs. vertical panning.
The above API gives a powerful tool for expressing all sorts of animations in a
concise, robust, and performant way. Check out more example code in
UIExplorer/AnimationExample. Of course there may still be times where Animated
doesn't support what you need, and the following sections cover other animation
-systems.
LayoutAnimation allows you to globally configure create and update
+systems.
LayoutAnimation allows you to globally configure create and update
animations that will be used for all views in the next render/layout cycle.
This is useful for doing flexbox layout updates without bothering to measure or
calculate specific properties in order to animate them directly, and is
@@ -179,12 +179,12 @@ what you want.

This example uses a preset value, you can customize the animations as you need, see LayoutAnimation.js -for more information.
requestAnimationFrame is a polyfill from the browser that you might be
+for more information.
requestAnimationFrame is a polyfill from the browser that you might be
familiar with. It accepts a function as its only argument and calls that
function before the next repaint. It is an essential building block for
animations that underlies all of the JavaScript-based animation APIs. In
general, you shouldn't need to call this yourself - the animation APIs will
-manage frame updates for you.
react-tween-state is a +manage frame updates for you.
react-tween-state is a minimal library that does exactly what its name suggests: it tweens a value in a component's state, starting at a from value and ending at a to value. This means that it generates the values in between those @@ -200,7 +200,7 @@ Linear easing often looks awkward and unnatural, so react-tween-state provides a selection of popular easing functions that can be applied to make your animations more pleasing.
This library does not ship with React Native - in order to use it on
your project, you will need to install it with npm i react-tween-state
---save from your project directory.
npm i react-tween-state
},
});
Here we animated the opacity, but as you might guess, we can animate any numeric value. Read more about react-tween-state in its -README.
Rebound.js is a JavaScript port of +README.
Rebound.js is a JavaScript port of Rebound for Android. It is similar in concept to react-tween-state: you have an initial value and set an end value, then Rebound generates intermediate values that you can @@ -241,7 +241,7 @@ value and end value. Rebound
Notice that Rebound animations can be interrupted - if you release in the middle of a press, it will animate back from the current state to -the original value.
Screenshot from
react-native-scrollable-tab-view.
-You can run a similar example here.
As mentioned in the Direction Manipulation section, +You can run a similar example here.
As mentioned in the Direction Manipulation section,
setNativeProps allows us to modify properties of native-backed
components (components that are actually backed by native views, unlike
composite components) directly, without having to setState and
@@ -336,15 +336,14 @@ computationally intensive work until after animations are complete,
using the
InteractionManager. You
can monitor the frame rate by using the In-App Developer Menu "FPS
-Monitor" tool.
As mentioned in the Navigator +Monitor" tool.
As mentioned in the Navigator
Comparison,
Navigator is implemented in JavaScript and NavigatorIOS is a wrapper
around native functionality provided by UINavigationController, so
these scene transitions apply only to Navigator. In order to re-create
the various animations provided by UINavigationController and also
make them customizable, React Native exposes a
-NavigatorSceneConfigs API.
For further information about customizing scene transitions, read the -source.
AppRegistry # | Edit on GitHub |
AppRegistry is the JS entry point to running all React Native apps. App
+
AppRegistry # | Edit on GitHub |
AppRegistry is the JS entry point to running all React Native apps. App
root components should register themselves with
AppRegistry.registerComponent, then the native system can load the bundle
for the app and then actually run the app when it's ready by invoking
@@ -6,7 +6,7 @@ for the app and then actually run the app when it's ready by invoking
AppRegistry.unmountApplicationComponentAtRootTag with the tag that was
pass into runApplication. These should always be used as a pair.
AppRegistry should be required early in the require sequence to make
sure the JS execution environment is setup before other modules are
-required.
AppState # | Edit on GitHub |
AppState can tell you if the app is in the foreground or background,
+
AppState # | Edit on GitHub |
AppState can tell you if the app is in the foreground or background,
and notify you when the state changes.
AppState is frequently used to determine the intent and proper behavior when -handling push notifications.
active - The app is running in the foregroundbackground - The app is running in the background. The user is either
+handling push notifications.active - The app is running in the foregroundbackground - The app is running in the background. The user is either
in another app or on the home screeninactive - This is a transition state that currently never happens for
typical React Native apps.For more information, see -Apple's documentation
To see the current state, you can check AppState.currentState, which
+Apple's documentation
To see the current state, you can check AppState.currentState, which
will be kept up-to-date. However, currentState will be null at launch
while AppState retrieves it over the bridge.
This example will only ever appear to say "Current state is: active" because
the app is only visible to the user when in the active state, and the null
-state will happen only momentarily.
Examples # | Edit on GitHub |
Examples # | Edit on GitHub |
AppStateIOS # | Edit on GitHub |
AppStateIOS can tell you if the app is in the foreground or background,
+
AppStateIOS # | Edit on GitHub |
AppStateIOS can tell you if the app is in the foreground or background,
and notify you when the state changes.
AppStateIOS is frequently used to determine the intent and proper behavior when -handling push notifications.
active - The app is running in the foregroundbackground - The app is running in the background. The user is either
+handling push notifications.active - The app is running in the foregroundbackground - The app is running in the background. The user is either
in another app or on the home screeninactive - This is a transition state that currently never happens for
typical React Native apps.For more information, see -Apple's documentation
To see the current state, you can check AppStateIOS.currentState, which
+Apple's documentation
To see the current state, you can check AppStateIOS.currentState, which
will be kept up-to-date. However, currentState will be null at launch
while AppStateIOS retrieves it over the bridge.
This example will only ever appear to say "Current state is: active" because
the app is only visible to the user when in the active state, and the null
-state will happen only momentarily.
// TODO: getCurrentAppState callback seems to be called at a really late stage +state will happen only momentarily.
// TODO: getCurrentAppState callback seems to be called at a really late stage // after app launch. Trying to get currentState when mounting App component // will likely to have the initial value here. -// Initialize to 'active' instead of null.
Examples # | Edit on GitHub |
Examples # | Edit on GitHub |
AsyncStorage # | Edit on GitHub |
AsyncStorage is a simple, asynchronous, persistent, key-value storage +
AsyncStorage # | Edit on GitHub |
AsyncStorage is a simple, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage.
It is recommended that you use an abstraction on top of AsyncStorage instead of AsyncStorage directly for anything more than light usage since it operates globally.
This JS code is a simple facade over the native iOS implementation to provide
a clear JS API, real Error objects, and simple non-multi functions. Each
-method returns a Promise object.
Fetches key and passes the result to callback, along with an Error if
-there is any. Returns a Promise object.
Sets value for key and calls callback on completion, along with an
-Error if there is any. Returns a Promise object.
Returns a Promise object.
Merges existing value with input value, assuming they are stringified json.
-Returns a Promise object. Not supported by all native implementations.
Erases all AsyncStorage for all clients, libraries, etc. You probably
+method returns a Promise object.
Fetches key and passes the result to callback, along with an Error if
+there is any. Returns a Promise object.
Sets value for key and calls callback on completion, along with an
+Error if there is any. Returns a Promise object.
Returns a Promise object.
Merges existing value with input value, assuming they are stringified json.
+Returns a Promise object. Not supported by all native implementations.
Erases all AsyncStorage for all clients, libraries, etc. You probably
don't want to call this - use removeItem or multiRemove to clear only your
-own keys instead. Returns a Promise object.
Gets all keys known to the app, for all callers, libraries, etc. Returns a Promise object.
Flushes any pending requests using a single multiget
multiGet invokes callback with an array of key-value pair arrays that
-matches the input format of multiSet. Returns a Promise object.
multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])
multiSet and multiMerge take arrays of key-value array pairs that match
-the output of multiGet, e.g. Returns a Promise object.
multiSet([['k1', 'val1'], ['k2', 'val2']], cb);
Delete all the keys in the keys array. Returns a Promise object.
Merges existing values with input values, assuming they are stringified
-json. Returns a Promise object.
Not supported by all native implementations.
Examples # | Edit on GitHub |
Promise object.Gets all keys known to the app, for all callers, libraries, etc. Returns a Promise object.
Flushes any pending requests using a single multiget
multiGet invokes callback with an array of key-value pair arrays that
+matches the input format of multiSet. Returns a Promise object.
multiGet(['k1', 'k2'], cb) -> cb([['k1', 'val1'], ['k2', 'val2']])
multiSet and multiMerge take arrays of key-value array pairs that match
+the output of multiGet, e.g. Returns a Promise object.
multiSet([['k1', 'val1'], ['k2', 'val2']], cb);
Delete all the keys in the keys array. Returns a Promise object.
Merges existing values with input values, assuming they are stringified
+json. Returns a Promise object.
Not supported by all native implementations.
Examples # | Edit on GitHub |
BackAndroid # | Edit on GitHub |
Detect hardware back button presses, and programmatically invoke the default back button +
BackAndroid # | Edit on GitHub |
Detect hardware back button presses, and programmatically invoke the default back button functionality to exit the app if there are no listeners or if none of the listeners return true.
Example:
CameraRoll # | Edit on GitHub |
CameraRoll provides access to the local camera roll / gallery.
Saves the image to the camera roll / gallery.
On Android, the tag is a local URI, such as "file:///sdcard/img.png".
On iOS, the tag can be one of the following:
Returns a Promise which when resolved will be passed the new URI.
Returns a Promise with photo identifier objects from the local camera
-roll of the device matching shape defined by getPhotosReturnChecker.
@param {object} params See getPhotosParamChecker.
Returns a Promise which when resolved will be of shape getPhotosReturnChecker.
Examples # | Edit on GitHub |
CameraRoll # | Edit on GitHub |
CameraRoll provides access to the local camera roll / gallery.
Saves the image to the camera roll / gallery.
On Android, the tag is a local URI, such as "file:///sdcard/img.png".
On iOS, the tag can be one of the following:
Returns a Promise which when resolved will be passed the new URI.
Returns a Promise with photo identifier objects from the local camera
+roll of the device matching shape defined by getPhotosReturnChecker.
@param {object} params See getPhotosParamChecker.
Returns a Promise which when resolved will be of shape getPhotosReturnChecker.
Examples # | Edit on GitHub |
Colors # | Edit on GitHub |
The following formats are supported:
#f0f (#rgb)#f0fc (#rgba)#ff00ff (#rrggbb)#ff00ff00 (#rrggbbaa)rgb(255, 255, 255)rgba(255, 255, 255, 1.0)hsl(360, 100%, 100%)hsla(360, 100%, 100%, 1.0)transparentredFor the named colors, React Native follows the CSS3 specification:
Colors # | Edit on GitHub |
The following formats are supported:
'#f0f' (#rgb)'#f0fc' (#rgba)'#ff00ff' (#rrggbb)'#ff00ff00' (#rrggbbaa)'rgb(255, 255, 255)''rgba(255, 255, 255, 1.0)''hsl(360, 100%, 100%)''hsla(360, 100%, 100%, 1.0)''transparent''red'0xff00ff00 (0xrrggbbaa)For the named colors, React Native follows the CSS3 specification:
Communication between native and React Native # | Edit on GitHub |
In Integrating with Existing Apps guide and Native UI Components guide we learn how to embed React Native in a native component and vice versa. When we mix native and React Native components, we'll eventually find a need to communicate between these two worlds. Some ways to achieve that have been already mentioned in other guides. This article summarizes available techniques.
React Native is inspired by React, so the basic idea of the information flow is similar. The flow in React is one-directional. We maintain a hierarchy of components, in which each component depends only on its parent and own internal state. We do this with properties: data is passed from a parent to its children in a top-down manner. If we have an ancestor component that rely on the state of its descendant, the recommended solution would be to pass down a callback that would be used by the descendant to update the ancestor.
The same concept applies to React Native. As long as we are building our application purely within the framework, we can drive our app with properties and callbacks. But, when we mix React Native and native components, we need some special, cross-language mechanisms that would allow us to pass information between them.
Properties are the simplest way of cross-component communication. So we need a way to pass properties both from native to React Native, and from React Native to native.
In order to embed a React Native view in a native component, we use RCTRootView. RCTRootView is a UIView that holds a React Native app. It also provides an interface between native side and the hosted app.
RCTRootView has an initializer that allows you to pass arbitrary properties down to the React Native app. The initialProperties parameter has to be an instance of NSDictionary. The dictionary is internally converted into a JSON object that the top-level JS component can reference.
Communication between native and React Native # | Edit on GitHub |
In Integrating with Existing Apps guide and Native UI Components guide we learn how to embed React Native in a native component and vice versa. When we mix native and React Native components, we'll eventually find a need to communicate between these two worlds. Some ways to achieve that have been already mentioned in other guides. This article summarizes available techniques.
React Native is inspired by React, so the basic idea of the information flow is similar. The flow in React is one-directional. We maintain a hierarchy of components, in which each component depends only on its parent and own internal state. We do this with properties: data is passed from a parent to its children in a top-down manner. If we have an ancestor component that rely on the state of its descendant, the recommended solution would be to pass down a callback that would be used by the descendant to update the ancestor.
The same concept applies to React Native. As long as we are building our application purely within the framework, we can drive our app with properties and callbacks. But, when we mix React Native and native components, we need some special, cross-language mechanisms that would allow us to pass information between them.
Properties are the simplest way of cross-component communication. So we need a way to pass properties both from native to React Native, and from React Native to native.
In order to embed a React Native view in a native component, we use RCTRootView. RCTRootView is a UIView that holds a React Native app. It also provides an interface between native side and the hosted app.
RCTRootView has an initializer that allows you to pass arbitrary properties down to the React Native app. The initialProperties parameter has to be an instance of NSDictionary. The dictionary is internally converted into a JSON object that the top-level JS component can reference.
It is fine to update properties anytime. However, updates have to be performed on the main thread. You use the getter on any thread.
There is no way to update only a few properties at a time. We suggest that you build it into your own wrapper instead.
Note: -Currently, JS functions
componentWillReceivePropsandcomponentWillUpdatePropsof the top level RN component will not be called after a prop update. However, you can access the new props incomponentWillMountfunction.
The problem exposing properties of native components is covered in detail in this article. In short, export properties with RCT_CUSTOM_VIEW_PROPERTY macro in your custom native component, then just use them in React Native as if the component was an ordinary React Native component.
The main drawback of cross-language properties is that they do not support callbacks, which would allow us to handle bottom-up data bindings. Imagine you have a small RN view that you want to be removed from the native parent view as a result of a JS action. There is no way to do that with props, as the information would need to go bottom-up.
Although we have a flavor of cross-language callbacks (described here), these callbacks are not always the thing we need. The main problem is that they are not intended to be passed as properties. Rather, this mechanism allows us to trigger a native action from JS, and handle the result of that action in JS.
As stated in the previous chapter, using properties comes with some limitations. Sometimes properties are not enough to drive the logic of our app and we need a solution that gives more flexibility. This chapter covers other communication techniques available in React Native. They can be used for internal communication (between JS and native layers in RN) as well as for external communication (between RN and the 'pure native' part of your app).
React Native enables you to perform cross-language function calls. You can execute custom native code from JS and vice versa. Unfortunately, depending on the side we are working on, we achieve the same goal in different ways. For native - we use events mechanism to schedule an execution of a handler function in JS, while for React Native we directly call methods exported by native modules.
Events are described in detail in this article. Note that using events gives us no guarantees about execution time, as the event is handled on a separate thread.
Events are powerful, because they allow us to change React Native components without needing a reference to them. However, there are some pitfalls that you can fall into while using them:
reactTag as an identifier).The common pattern we use when embedding native in React Native is to make the native component's RCTViewManager a delegate for the views, sending events back to JavaScript via the bridge. This keeps related event calls in one place.
Native modules are Objective-C classes that are available in JS. Typically one instance of each module is created per JS bridge. They can export arbitrary functions and constants to React Native. They have been covered in detail in this article.
The fact that native modules are singletons limits the mechanism in context of embedding. Let's say we have a React Native component embedded in a native view and we want to update the native, parent view. Using the native module mechanism, we would export a function that not only takes expected arguments, but also an identifier of the parent native view. The identifier would be used to retrieve a reference to the parent view to update. That said, we would need to keep a mapping from identifiers to native views in the module.
Although this solution is complex, it is used in RCTUIManager, which is an internal React Native class that manages all React Native views.
Native modules can also be used to expose existing native libraries to JS. Geolocation library is a living example of the idea.
Warning: -All native modules share the same namespace. Watch out for name collisions when creating new ones.
When integrating native and React Native, we also need a way to consolidate two different layout systems. This section covers common layouting problems and provides a brief description of mechanisms that are intended to address them.
This case is covered in this article. Basically, as all our native react views are subclasses of UIView, most style and size attributes will work like you would expect out of the box.
The simplest scenario is when we have a React Native app with a fixed size, which is known to the native side. In particular, a full-screen React Native view falls into this case. If we want a smaller root view, we can explicitly set RCTRootView's frame.
For instance, to make an RN app 200 (logical) pixels high, and the hosting view's width wide, we could do:
componentWillReceiveProps and componentWillUpdateProps of the top level RN component will not be called after a prop update. However, you can access the new props in componentWillMount function.The problem exposing properties of native components is covered in detail in this article. In short, export properties with RCT_CUSTOM_VIEW_PROPERTY macro in your custom native component, then just use them in React Native as if the component was an ordinary React Native component.
The main drawback of cross-language properties is that they do not support callbacks, which would allow us to handle bottom-up data bindings. Imagine you have a small RN view that you want to be removed from the native parent view as a result of a JS action. There is no way to do that with props, as the information would need to go bottom-up.
Although we have a flavor of cross-language callbacks (described here), these callbacks are not always the thing we need. The main problem is that they are not intended to be passed as properties. Rather, this mechanism allows us to trigger a native action from JS, and handle the result of that action in JS.
As stated in the previous chapter, using properties comes with some limitations. Sometimes properties are not enough to drive the logic of our app and we need a solution that gives more flexibility. This chapter covers other communication techniques available in React Native. They can be used for internal communication (between JS and native layers in RN) as well as for external communication (between RN and the 'pure native' part of your app).
React Native enables you to perform cross-language function calls. You can execute custom native code from JS and vice versa. Unfortunately, depending on the side we are working on, we achieve the same goal in different ways. For native - we use events mechanism to schedule an execution of a handler function in JS, while for React Native we directly call methods exported by native modules.
Events are described in detail in this article. Note that using events gives us no guarantees about execution time, as the event is handled on a separate thread.
Events are powerful, because they allow us to change React Native components without needing a reference to them. However, there are some pitfalls that you can fall into while using them:
reactTag as an identifier).The common pattern we use when embedding native in React Native is to make the native component's RCTViewManager a delegate for the views, sending events back to JavaScript via the bridge. This keeps related event calls in one place.
Native modules are Objective-C classes that are available in JS. Typically one instance of each module is created per JS bridge. They can export arbitrary functions and constants to React Native. They have been covered in detail in this article.
The fact that native modules are singletons limits the mechanism in context of embedding. Let's say we have a React Native component embedded in a native view and we want to update the native, parent view. Using the native module mechanism, we would export a function that not only takes expected arguments, but also an identifier of the parent native view. The identifier would be used to retrieve a reference to the parent view to update. That said, we would need to keep a mapping from identifiers to native views in the module.
Although this solution is complex, it is used in RCTUIManager, which is an internal React Native class that manages all React Native views.
Native modules can also be used to expose existing native libraries to JS. Geolocation library is a living example of the idea.
Warning: +All native modules share the same namespace. Watch out for name collisions when creating new ones.
When integrating native and React Native, we also need a way to consolidate two different layout systems. This section covers common layouting problems and provides a brief description of mechanisms that are intended to address them.
This case is covered in this article. Basically, as all our native react views are subclasses of UIView, most style and size attributes will work like you would expect out of the box.
The simplest scenario is when we have a React Native app with a fixed size, which is known to the native side. In particular, a full-screen React Native view falls into this case. If we want a smaller root view, we can explicitly set RCTRootView's frame.
For instance, to make an RN app 200 (logical) pixels high, and the hosting view's width wide, we could do:
When we have a fixed size root view, we need to respect its bounds on the JS side. In other words, we need to ensure that the React Native content can be contained within the fixed-size root view. The easiest way to ensure this is to use flexbox layout. If you use absolute positioning, and React components are visible outside the root view's bounds, you'll get overlap with native views, causing some features to behave unexpectedly. For instance, 'TouchableHighlight' will not highlight your touches outside the root view's bounds.
It's totally fine to update root view's size dynamically by re-setting its frame property. React Native will take care of the content's layout.
In some cases we'd like to render content of initially unknown size. Let's say the size will be defined dynamically in JS. We have two solutions to this problem.
ScrollView component. This guarantees that your content will always be available and it won't overlap with native views.RCTRootView. The owner is then responsible for re-laying out the subviews and keeping the UI consistent. We achieve this with RCTRootView's flexibility modes.RCTRootView supports 4 different size flexibility modes:
When we have a fixed size root view, we need to respect its bounds on the JS side. In other words, we need to ensure that the React Native content can be contained within the fixed-size root view. The easiest way to ensure this is to use flexbox layout. If you use absolute positioning, and React components are visible outside the root view's bounds, you'll get overlap with native views, causing some features to behave unexpectedly. For instance, 'TouchableHighlight' will not highlight your touches outside the root view's bounds.
It's totally fine to update root view's size dynamically by re-setting its frame property. React Native will take care of the content's layout.
In some cases we'd like to render content of initially unknown size. Let's say the size will be defined dynamically in JS. We have two solutions to this problem.
ScrollView component. This guarantees that your content will always be available and it won't overlap with native views.RCTRootView. The owner is then responsible for re-laying out the subviews and keeping the UI consistent. We achieve this with RCTRootView's flexibility modes.RCTRootView supports 4 different size flexibility modes:
In the example we have a FlexibleSizeExampleView view that holds a root view. We create the root view, initialize it and set the delegate. The delegate will handle size updates. Then, we set the root view's size flexibility to RCTRootViewSizeFlexibilityHeight, which means that rootViewDidChangeIntrinsicSize: method will be called every time the React Native content changes its height. Finally, we set the root view's width and position. Note that we set there height as well, but it has no effect as we made the height RN-dependent.
You can checkout full source code of the example here.
It's fine to change root view's size flexibility mode dynamically. Changing flexibility mode of a root view will schedule a layout recalculation and the delegate rootViewDidChangeIntrinsicSize: method will be called once the content size is known.
Note: React Native layout calculation is performed on a special thread, while native UI view updates are done on the main thread. This may cause temporary UI inconsistencies between native and React Native. This is a known problem and our team is working on synchronizing UI updates coming from different sources.
Note: React Native does not perform any layout calculations until the root view becomes a subview of some other views. If you want to hide React Native view until its dimensions are known, add the root view as a subview and make it initially hidden (use
UIView'shiddenproperty). Then change its visibility in the delegate method.
DatePickerAndroid # | Edit on GitHub |
Opens the standard Android date picker dialog.
Opens the standard Android date picker dialog.
The available keys for the options object are:
+ date (Date object or timestamp in milliseconds) - date to show by default
+ minDate (Date or timestamp in milliseconds) - minimum date that can be selected
+ * maxDate (Date object or timestamp in milliseconds) - minimum date that can be selected
Returns a Promise which will be invoked an object containing action, year, month (0-11),
+day if the user picked a date. If the user dismissed the dialog, the Promise will
+still be resolved with action being DatePickerAndroid.dismissedAction and all the other keys
+being undefined. Always check whether the action before reading the values.
Note the native date picker dialog has some UI glitches on Android 4 and lower
+when using the minDate and maxDate options.
A date has been selected.
The dialog has been dismissed.
Examples # | Edit on GitHub |
DatePickerIOS # | Edit on GitHub |
Use DatePickerIOS to render a date/time picker (selector) on iOS. This is
+
DatePickerIOS # | Edit on GitHub |
Use DatePickerIOS to render a date/time picker (selector) on iOS. This is
a controlled component, so you must hook in to the onDateChange callback
and update the date prop in order for the component to update, otherwise
the user's change will be reverted immediately to reflect props.date as the
-source of truth.
The currently selected date.
Maximum date.
Restricts the range of possible date/time values.
Minimum date.
Restricts the range of possible date/time values.
The interval at which minutes can be selected.
The date picker mode.
Date change handler.
This is called when the user changes the date or time in the UI. +source of truth.
The currently selected date.
Maximum date.
Restricts the range of possible date/time values.
Minimum date.
Restricts the range of possible date/time values.
The interval at which minutes can be selected.
The date picker mode.
Date change handler.
This is called when the user changes the date or time in the UI. The first and only argument is a Date object representing the new -date and time.
Timezone offset in minutes.
By default, the date picker will use the device's timezone. With this +date and time.
Timezone offset in minutes.
By default, the date picker will use the device's timezone. With this parameter, it is possible to force a certain timezone offset. For -instance, to show times in Pacific Standard Time, pass -7 * 60.
Examples # | Edit on GitHub |
Examples # | Edit on GitHub |
Debugging # | Edit on GitHub |
To access the in-app developer menu:
control + ⌘ + z in the simulator.⌘ + m to simulate hardware menu button click). You can also install Frappé, a tool for OS X, which allows you to emulate shaking of devices remotely. You can use ⌘ + Shift + R as a shortcut to trigger a shake from Frappé.Hint
To disable the developer menu for production builds:
- For iOS open your project in Xcode and select
Product→Scheme→Edit Scheme...(or press⌘ + <). Next, selectRunfrom the menu on the left and change the Build Configuration toRelease.- For Android, by default, developer menu will be disabled in release builds done by gradle (e.g with gradle
assembleReleasetask). Although this behavior can be customized by passing proper value toReactInstanceManager#setUseDeveloperSupport.
Selecting Reload (or pressing ⌘ + r in the iOS simulator) will reload the JavaScript that powers your application. If you have added new resources (such as an image to Images.xcassets on iOS or to res/drawable folder on Android) or modified any native code (Objective-C/Swift code on iOS or Java/C++ code on Android), you will need to re-build the app for the changes to take effect.
To debug the JavaScript code in Chrome, select Debug in Chrome from the developer menu. This will open a new tab at http://localhost:8081/debugger-ui.
In Chrome, press ⌘ + option + i or select View → Developer → Developer Tools to toggle the developer tools console. Enable Pause On Caught Exceptions for a better debugging experience.
To debug on a real device:
RCTWebSocketExecutor.m and change localhost to the IP address of your computer. Shake the device to open the development menu with the option to start debugging.adb command line tool to setup port forwarding from the device to your computer. For that run: adb reverse tcp:8081 tcp:8081 (see this link for help on adb command). Alternatively, you can open dev menu on the device and select Dev Settings, then update Debug server host for device setting to the IP address of your computer.Install the React Developer Tools extension for Google Chrome. This will allow you to navigate the component hierarchy via the React in the developer tools (see facebook/react-devtools for more information).
This option allows for your JS changes to trigger automatic reload on the connected device/emulator. To enable this option:
Enable Live Reload via the developer menu to have the application automatically reload when changes are made to the JavaScript.Dev Settings and select Auto reload on JS change optionOn 0.5.0-rc and higher versions, you can enable a FPS graph overlay in the developers menu in order to help you debug performance problems.
Debugging # | Edit on GitHub |
To access the in-app developer menu:
control + ⌘ + z in the simulator.⌘ + m to simulate hardware menu button click). You can also install Frappé, a tool for OS X, which allows you to emulate shaking of devices remotely. You can use ⌘ + Shift + R as a shortcut to trigger a shake from Frappé.Hint
To disable the developer menu for production builds:
- For iOS open your project in Xcode and select
Product→Scheme→Edit Scheme...(or press⌘ + <). Next, selectRunfrom the menu on the left and change the Build Configuration toRelease.- For Android, by default, developer menu will be disabled in release builds done by gradle (e.g with gradle
assembleReleasetask). Although this behavior can be customized by passing proper value toReactInstanceManager#setUseDeveloperSupport.
Run adb logcat *:S ReactNative:V ReactNativeJS:V in a terminal to see your Android app's logs.
Selecting Reload (or pressing ⌘ + r in the iOS simulator) will reload the JavaScript that powers your application. If you have added new resources (such as an image to Images.xcassets on iOS or to res/drawable folder on Android) or modified any native code (Objective-C/Swift code on iOS or Java/C++ code on Android), you will need to re-build the app for the changes to take effect.
Using console.warn will display an on-screen log on a yellow background. Click on this warning to show more information about it full screen and/or dismiss the warning.
You can use console.error to display a full screen error on a red background.
These boxes only appear when you're running your app in dev mode.
To debug the JavaScript code in Chrome, select Debug in Chrome from the developer menu. This will open a new tab at http://localhost:8081/debugger-ui.
In Chrome, press ⌘ + option + i or select View → Developer → Developer Tools to toggle the developer tools console. Enable Pause On Caught Exceptions for a better debugging experience.
To debug on a real device:
RCTWebSocketExecutor.m and change localhost to the IP address of your computer. Shake the device to open the development menu with the option to start debugging.adb command line tool to setup port forwarding from the device to your computer. For that run: adb reverse tcp:8081 tcp:8081 (see this link for help on adb command). Alternatively, you can open dev menu on the device and select Dev Settings, then update Debug server host for device setting to the IP address of your computer.Install the React Developer Tools extension for Google Chrome. This will allow you to navigate the component hierarchy via the React in the developer tools (see facebook/react-devtools for more information).
This option allows for your JS changes to trigger automatic reload on the connected device/emulator. To enable this option:
Enable Live Reload via the developer menu to have the application automatically reload when changes are made to the JavaScript.Dev Settings and select Auto reload on JS change optionOn 0.5.0-rc and higher versions, you can enable a FPS graph overlay in the developers menu in order to help you debug performance problems.
Dimensions # | Edit on GitHub |
This should only be called from native code.
@param {object} dims Simple string-keyed object of dimensions to set
Initial dimensions are set before runApplication is called so they should
+
Dimensions # | Edit on GitHub |
This should only be called from native code.
@param {object} dims Simple string-keyed object of dimensions to set
Initial dimensions are set before runApplication is called so they should
be available before any other require's are run, but may be updated later.
Note: Although dimensions are available immediately, they may change (e.g
due to device rotation) so any rendering logic or styles that depend on
these constants should try to call this function on every render, rather
than caching the value (for example, using inline styles rather than
setting a value in a StyleSheet).
Example: var {height, width} = Dimensions.get('window');
@param {string} dim Name of dimension as defined when calling set.
-@returns {Object?} Value for the dimension.
Direct Manipulation # | Edit on GitHub |
It is sometimes necessary to make changes directly to a component +
Direct Manipulation # | Edit on GitHub |
It is sometimes necessary to make changes directly to a component
without using state/props to trigger a re-render of the entire subtree.
When using React in the browser for example, you sometimes need to
directly modify a DOM node, and the same is true for views in mobile
@@ -10,7 +10,7 @@ hierarchy and reconciling many views. setNativeProps is imperative
and stores state in the native layer (DOM, UIView, etc.) and not
within your React components, which makes your code more difficult to
reason about. Before you use it, try to solve your problem with setState
-and shouldComponentUpdate.
TouchableOpacity +and shouldComponentUpdate.
TouchableOpacity
uses setNativeProps internally to update the opacity of its child
component:
If
you will notice that it is a wrapper around RCTUIManager.updateView -
this is the exact same function call that results from re-rendering -
see receiveComponent in
-ReactNativeBaseComponent.js.
Composite components are not backed by a native view, so you cannot call +ReactNativeBaseComponent.js.
Composite components are not backed by a native view, so you cannot call
setNativeProps on them. Consider this example:
React.createClass you would not expect to b
able to set a style prop on it and have that work - you would need to
pass the style prop down to a child, unless you are wrapping a native
component. Similarly, we are going to forward setNativeProps to a
-native-backed child component.All we need to do is provide a setNativeProps method on our component
+native-backed child component.
All we need to do is provide a setNativeProps method on our component
that calls setNativeProps on the appropriate child with the given
arguments.
Another very common use case of setNativeProps is to clear the value
+requires that we implement setNativeProps.
Another very common use case of setNativeProps is to clear the value
of a TextInput. The controlled prop of TextInput can sometimes drop
characters when the bufferDelay is low and the user types very
quickly. Some developers prefer to skip this prop entirely and instead
@@ -120,17 +120,17 @@ input when you tap a button:
If you update a property that is also managed by the render function, +});
If you update a property that is also managed by the render function,
you might end up with some unpredictable and confusing bugs because
anytime the component re-renders and that property changes, whatever
value was previously set from setNativeProps will be completely
ignored and overridden. See this example
for a demonstration of what can happen if these two collide - notice
-the jerky animation each 250ms when setState triggers a re-render.
By intelligently applying
+the jerky animation each 250ms when setState triggers a re-render.
By intelligently applying
shouldComponentUpdate
you can avoid the unnecessary overhead involved in reconciling unchanged
component subtrees, to the point where it may be performant enough to
-use setState instead of setNativeProps.
DrawerLayoutAndroid # | Edit on GitHub |
React component that wraps the platform DrawerLayout (Android only). The
+
DrawerLayoutAndroid # | Edit on GitHub |
React component that wraps the platform DrawerLayout (Android only). The
Drawer (typically used for navigation) is rendered with renderNavigationView
and direct children are the main view (where your content goes). The navigation
view is initially not visible on the screen, but can be pulled in from the
@@ -20,14 +20,14 @@ be set by the drawerWidth prop.
Example:
Specifies the side of the screen from which the drawer will slide in.
Specifies the width of the drawer, more precisely the width of the view that be pulled in -from the edge of the window.
Determines whether the keyboard gets dismissed in response to a drag. +},
Specifies the side of the screen from which the drawer will slide in.
Specifies the width of the drawer, more precisely the width of the view that be pulled in +from the edge of the window.
Determines whether the keyboard gets dismissed in response to a drag. - 'none' (the default), drags do not dismiss the keyboard. - - 'on-drag', the keyboard is dismissed when a drag begins.
Function called whenever the navigation view has been closed.
Function called whenever the navigation view has been opened.
Function called whenever there is an interaction with the navigation view.
Function called when the drawer state has changed. The drawer can be in 3 states: + - 'on-drag', the keyboard is dismissed when a drag begins.
Function called whenever the navigation view has been closed.
Function called whenever the navigation view has been opened.
Function called whenever there is an interaction with the navigation view.
Function called when the drawer state has changed. The drawer can be in 3 states: - idle, meaning there is no interaction with the navigation view happening at the time - dragging, meaning there is currently an interaction with the navigation view - settling, meaning that there was an interaction with the navigation view, and the -navigation view is now finishing it's closing or opening animation
The navigation view that will be rendered to the side of the screen and can be pulled in.
Integrating with Existing Apps # | Edit on GitHub |
Since React makes no assumptions about the rest of your technology stack, it's easily embeddable within an existing non-React Native app.
In your app's build.gradle file add the React Native dependency:
You can find the latest version of the react-native library on Maven Central. Next, make sure you have the Internet permission in your AndroidManifest.xml:
This is only really used in dev mode when reloading JavaScript from the development server, so you can strip this in release builds if you need to.
You need to add some native code in order to start the React Native runtime and get it to render something. To do this, we're going to create an Activity that creates a ReactRootView, starts a React application inside it and sets it as the main content view.
Integrating with Existing Apps # | Edit on GitHub |
Since React makes no assumptions about the rest of your technology stack, it's easily embeddable within an existing non-React Native app.
In your app's build.gradle file add the React Native dependency:
You can find the latest version of the react-native library on Maven Central. Next, make sure you have the Internet permission in your AndroidManifest.xml:
This is only really used in dev mode when reloading JavaScript from the development server, so you can strip this in release builds if you need to.
You need to add some native code in order to start the React Native runtime and get it to render something. To do this, we're going to create an Activity that creates a ReactRootView, starts a React application inside it and sets it as the main content view.
That's it, your activity is ready to run some JavaScript code.
In your project's root folder, run:
That's it, your activity is ready to run some JavaScript code.
In your project's root folder, run:
This creates a node module for your app and adds the react-native npm dependency. Now open the newly created package.json file and add this under scripts:
Copy & paste the following code to index.android.js in your root folder — it's a barebones React Native app:
To run your app, you need to first start the development server. To do this, simply run the following command in your root folder:
Now build and run your Android app as normal (e.g. ./gradlew installDebug). Once you reach your React-powered activity inside the app, it should load the JavaScript code from the development server and display:

You can have multiple Activities or Fragments that use the same ReactInstanceManager. You'll want to make your own "ReactFragment" or "ReactActivity" and have a singleton "holder" that holds a ReactInstanceManager. When you need the ReactInstanceManager / hook up the ReactInstanceManager to the lifecycle of those Activities or Fragments, use the one provided by the singleton.
Integrating with Existing Apps # | Edit on GitHub |
Since React makes no assumptions about the rest of your technology stack – it’s commonly noted as simply the V in MVC – it’s easily embeddable within an existing non-React Native app. In fact, it integrates with other best practice community tools like CocoaPods.
gem install cocoapodsnvm install node && nvm alias default node, which installs the latest version of Node.js and sets up your terminal so you can run it by typing node. With nvm you can install multiple versions of Node.js and easily switch between them.react-native package from npm by running the following command in the root directory of your project:npm install react-nativeAt this point you should have the React Native package installed under a directory named node_modules as a sibling to your .xcodeproj file.
CocoaPods is a package management tool for iOS/Mac development. We need to use it to download React Native. If you haven't installed CocoaPods yet, check out this tutorial.
When you are ready to work with CocoaPods, add the following lines to Podfile. If you don't have one, then create it under the root directory of your project.
Integrating with Existing Apps # | Edit on GitHub |
Since React makes no assumptions about the rest of your technology stack – it’s commonly noted as simply the V in MVC – it’s easily embeddable within an existing non-React Native app. In fact, it integrates with other best practice community tools like CocoaPods.
gem install cocoapodsnvm install node && nvm alias default node, which installs the latest version of Node.js and sets up your terminal so you can run it by typing node. With nvm you can install multiple versions of Node.js and easily switch between them.react-native package from npm by running the following command in the root directory of your project:npm install react-nativeAt this point you should have the React Native package installed under a directory named node_modules as a sibling to your .xcodeproj file.
CocoaPods is a package management tool for iOS/Mac development. We need to use it to download React Native. If you haven't installed CocoaPods yet, check out this tutorial.
When you are ready to work with CocoaPods, add the following lines to Podfile. If you don't have one, then create it under the root directory of your project.
Remember to install all subspecs you need. The <Text> element cannot be used without the RCTText subspec, for example.
Then install your pods:
There are two pieces you’ll need to set up:
RCTRootView to display and manage your React Native componentsFirst, create a directory for your app’s React code and create a simple index.ios.js file:
Remember to install all subspecs you need. The <Text> element cannot be used without the RCTText subspec, for example.
Then install your pods:
There are two pieces you’ll need to set up:
RCTRootView to display and manage your React Native componentsFirst, create a directory for your app’s React code and create a simple index.ios.js file:
Copy & paste following starter code for index.ios.js – it’s a barebones React Native app:
SimpleApp will be your module name, which will be used later on.
You should now add a container view for the React Native component. It can be any UIView in your app.

However, let's subclass UIView for the sake of clean code. Let's name it ReactView. Open up Yourproject.xcworkspace and create a new class ReactView (You can name it whatever you like :)).
SimpleApp will be your module name, which will be used later on.
You should now add a container view for the React Native component. It can be any UIView in your app.

However, let's subclass UIView for the sake of clean code. Let's name it ReactView. Open up Yourproject.xcworkspace and create a new class ReactView (You can name it whatever you like :)).
Here I disabled AutoLayout for simplicity. In real production world, you should turn on AutoLayout and setup constraints by yourself.
Ready for the most interesting part? Now we shall create the RCTRootView, where your React Native app lives.
In ReactView.m, we need to first initiate RCTRootView with the URI of your index.ios.bundle. index.ios.bundle will be created by packager and served by React Native server, which will be discussed later on.
Here I disabled AutoLayout for simplicity. In real production world, you should turn on AutoLayout and setup constraints by yourself.
Ready for the most interesting part? Now we shall create the RCTRootView, where your React Native app lives.
In ReactView.m, we need to first initiate RCTRootView with the URI of your index.ios.bundle. index.ios.bundle will be created by packager and served by React Native server, which will be discussed later on.
Then add it as a subview of the ReactView.
In root directory, we need to start React Native development server.
This command will start up a React Native development server within our CocoaPods dependency to build our bundled script. The --root option indicates the root of your React Native apps – this will be our ReactComponents directory containing the single index.ios.js file. This running server will package up the index.ios.bundle file accessible via http://localhost:8081/index.ios.bundle.
On iOS 9 and above the app won't be a able to connect over http to localhost unless specifically told so. See this thread for alternatives and instructions: http://stackoverflow.com/questions/31254725/transport-security-has-blocked-a-cleartext-http.
It is recommended that you add an App Transport Security exception for localhost in your app's Info.plist file:
In root directory, we need to start React Native development server.
This command will start up a React Native development server within our CocoaPods dependency to build our bundled script. The --root option indicates the root of your React Native apps – this will be our ReactComponents directory containing the single index.ios.js file. This running server will package up the index.ios.bundle file accessible via http://localhost:8081/index.ios.bundle.
On iOS 9 and above the app won't be a able to connect over http to localhost unless specifically told so. See this thread for alternatives and instructions: http://stackoverflow.com/questions/31254725/transport-security-has-blocked-a-cleartext-http.
It is recommended that you add an App Transport Security exception for localhost in your app's Info.plist file:
If you don't do this, you will see the error - Could not connect to development server. when connecting to your server over http.
Now compile and run your app. You shall now see your React Native app running inside of the ReactView.

Live reload and all of the debugging tools will work from the simulator (make sure that DEBUG=1 is set under Build Settings -> Preprocessor Macros). You've got a simple React component totally encapsulated behind an Objective-C UIView subclass.
So under the hood, when RCTRootView is initialized, it will try to download, parse and run the bundle file from React Native development server. This means all you need to do is to implement your own container view or view controller for the RCTRootView – the RCTRootView ingests your bundled JS and renders your React components. Bravo!
You can checkout full source code of a sample application here.
Flexbox # | Edit on GitHub |
Flexbox # | Edit on GitHub |
Geolocation # | Edit on GitHub |
The Geolocation API follows the web spec: -https://developer.mozilla.org/en-US/docs/Web/API/Geolocation
You need to include the NSLocationWhenInUseUsageDescription key
+
Geolocation # | Edit on GitHub |
The Geolocation API follows the web spec: +https://developer.mozilla.org/en-US/docs/Web/API/Geolocation
You need to include the NSLocationWhenInUseUsageDescription key
in Info.plist to enable geolocation. Geolocation is enabled by default
-when you create a project with react-native init.
To request access to location, you need to add the following line to your
-app's AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Invokes the success callback once with the latest location info. Supported -options: timeout (ms), maximumAge (ms), enableHighAccuracy (bool)
Invokes the success callback whenever the location changes. Supported -options: timeout (ms), maximumAge (ms), enableHighAccuracy (bool)
Examples # | Edit on GitHub |
react-native init.To request access to location, you need to add the following line to your
+app's AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Invokes the success callback once with the latest location info. Supported +options: timeout (ms), maximumAge (ms), enableHighAccuracy (bool)
Invokes the success callback whenever the location changes. Supported +options: timeout (ms), maximumAge (ms), enableHighAccuracy (bool), distanceFilter(m)
Examples # | Edit on GitHub |
Gesture Responder System # | Edit on GitHub |
Gesture recognition on mobile devices is much more complicated than web. A touch can go through several phases as the app determines what the user's intention is. For example, the app needs to determine if the touch is scrolling, sliding on a widget, or tapping. This can even change during the duration of a touch. There can also be multiple simultaneous touches.
The touch responder system is needed to allow components to negotiate these touch interactions without any additional knowledge about their parent or child components. This system is implemented in ResponderEventPlugin.js, which contains further details and documentation.
Users can feel huge differences in the usability of web apps vs. native, and this is one of the big causes. Every action should have the following attributes:
These features make users more comfortable while using an app, because it allows people to experiment and interact without fear of making mistakes.
The responder system can be complicated to use. So we have provided an abstract Touchable implementation for things that should be "tappable". This uses the responder system and allows you to easily configure tap interactions declaratively. Use TouchableHighlight anywhere where you would use a button or link on web.
A view can become the touch responder by implementing the correct negotiation methods. There are two methods to ask the view if it wants to become responder:
View.props.onStartShouldSetResponder: (evt) => true, - Does this view want to become responder on the start of a touch?View.props.onMoveShouldSetResponder: (evt) => true, - Called for every touch move on the View when it is not the responder: does this view want to "claim" touch responsiveness?If the View returns true and attempts to become the responder, one of the following will happen:
View.props.onResponderGrant: (evt) => {} - The View is now responding for touch events. This is the time to highlight and show the user what is happeningView.props.onResponderReject: (evt) => {} - Something else is the responder right now and will not release itIf the view is responding, the following handlers can be called:
View.props.onResponderMove: (evt) => {} - The user is moving their fingerView.props.onResponderRelease: (evt) => {} - Fired at the end of the touch, ie "touchUp"View.props.onResponderTerminationRequest: (evt) => true - Something else wants to become responder. Should this view release the responder? Returning true allows releaseView.props.onResponderTerminate: (evt) => {} - The responder has been taken from the View. Might be taken by other views after a call to onResponderTerminationRequest, or might be taken by the OS without asking (happens with control center/ notification center on iOS)evt is a synthetic touch event with the following form:
nativeEventchangedTouches - Array of all touch events that have changed since the last eventidentifier - The ID of the touchlocationX - The X position of the touch, relative to the elementlocationY - The Y position of the touch, relative to the elementpageX - The X position of the touch, relative to the root elementpageY - The Y position of the touch, relative to the root elementtarget - The node id of the element receiving the touch eventtimestamp - A time identifier for the touch, useful for velocity calculationtouches - Array of all current touches on the screenonStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable.
However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true.
View.props.onStartShouldSetResponderCapture: (evt) => true,View.props.onMoveShouldSetResponderCapture: (evt) => true,For higher-level gesture interpretation, check out PanResponder.
Gesture Responder System # | Edit on GitHub |
Gesture recognition on mobile devices is much more complicated than web. A touch can go through several phases as the app determines what the user's intention is. For example, the app needs to determine if the touch is scrolling, sliding on a widget, or tapping. This can even change during the duration of a touch. There can also be multiple simultaneous touches.
The touch responder system is needed to allow components to negotiate these touch interactions without any additional knowledge about their parent or child components. This system is implemented in ResponderEventPlugin.js, which contains further details and documentation.
Users can feel huge differences in the usability of web apps vs. native, and this is one of the big causes. Every action should have the following attributes:
These features make users more comfortable while using an app, because it allows people to experiment and interact without fear of making mistakes.
The responder system can be complicated to use. So we have provided an abstract Touchable implementation for things that should be "tappable". This uses the responder system and allows you to easily configure tap interactions declaratively. Use TouchableHighlight anywhere where you would use a button or link on web.
A view can become the touch responder by implementing the correct negotiation methods. There are two methods to ask the view if it wants to become responder:
View.props.onStartShouldSetResponder: (evt) => true, - Does this view want to become responder on the start of a touch?View.props.onMoveShouldSetResponder: (evt) => true, - Called for every touch move on the View when it is not the responder: does this view want to "claim" touch responsiveness?If the View returns true and attempts to become the responder, one of the following will happen:
View.props.onResponderGrant: (evt) => {} - The View is now responding for touch events. This is the time to highlight and show the user what is happeningView.props.onResponderReject: (evt) => {} - Something else is the responder right now and will not release itIf the view is responding, the following handlers can be called:
View.props.onResponderMove: (evt) => {} - The user is moving their fingerView.props.onResponderRelease: (evt) => {} - Fired at the end of the touch, ie "touchUp"View.props.onResponderTerminationRequest: (evt) => true - Something else wants to become responder. Should this view release the responder? Returning true allows releaseView.props.onResponderTerminate: (evt) => {} - The responder has been taken from the View. Might be taken by other views after a call to onResponderTerminationRequest, or might be taken by the OS without asking (happens with control center/ notification center on iOS)evt is a synthetic touch event with the following form:
nativeEventchangedTouches - Array of all touch events that have changed since the last eventidentifier - The ID of the touchlocationX - The X position of the touch, relative to the elementlocationY - The Y position of the touch, relative to the elementpageX - The X position of the touch, relative to the root elementpageY - The Y position of the touch, relative to the root elementtarget - The node id of the element receiving the touch eventtimestamp - A time identifier for the touch, useful for velocity calculationtouches - Array of all current touches on the screenonStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern, where the deepest node is called first. That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers. This is desirable in most cases, because it makes sure all controls and buttons are usable.
However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing on*ShouldSetResponderCapture. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a onStartShouldSetResponderCapture handler which returns true.
View.props.onStartShouldSetResponderCapture: (evt) => true,View.props.onMoveShouldSetResponderCapture: (evt) => true,For higher-level gesture interpretation, check out PanResponder.
Getting Started on Linux # | Edit on GitHub |
This guide is essentially a beginner-friendly version of the Getting Started page for React Native on Linux.
For the purposes of this guide, we assume that you're working on Ubuntu Linux 14.04 LTS.
Before following this guide, you should have installed the Android SDK and run a successful Java-based "Hello World" app for Android.
See Android Setup for details.
The first thing you need to do is to install NodeJS, a popular Javascript implementation.
Fire up the Terminal and paste the following commands to install NodeJS from the NodeSource repository:
NOTE: The above instructions are for Ubuntu. If you're on a different distro, please follow the instructions on the NodeJS website.
watchman is a tool by Facebook for watching changes in the filesystem. You need to install it for better performance and avoid a node file-watching bug.
Paste the following into your terminal to compile watchman from source and install it:
Flow is a static type checker for JavaScript. To install it, paste the following in the terminal:
Let's set up an Android device to run our starter project.
First thing is to plug in your device and check the manufacturer code by using lsusb, which should output something like this:
These lines represent the USB devices currently connected to your machine.
You want the line that represents your phone. If you're in doubt, try unplugging your phone and running the command again:
You'll see that after removing the phone, the line which has the phone model ("Motorola PCS" in this case) disappeared from the list. This is the line that we care about.
Bus 001 Device 003: ID 22b8:2e76 Motorola PCS
From the above line, you want to grab the first four digits from the device ID:
22b8:2e76
In this case, it's 22b8. That's the identifier for Motorola.
You'll need to input this into your udev rules in order to get up and running:
Make sure that you replace 22b8 with the identifier you get in the above command.
Now check that your device is properly connecting to ADB, the Android Debug Bridge, by using adb devices.
For more information, please see the docs for running an Android app on your device.
Your Android device and your tools are all ready to go. You can now follow the instructions in the Quick Start guide to install React Native and start your first project.
Getting Started # | Edit on GitHub |
nvm install node && nvm alias default node, which installs the latest version of Node.js and sets up your terminal so you can run it by typing node. With nvm you can install multiple versions of Node.js and easily switch between them.brew install watchman. We recommend installing watchman, otherwise you might hit a node file watching bug.brew install flow, if you want to use flow.We recommend periodically running brew update && brew upgrade to keep your programs up-to-date.
Xcode 7.0 or higher is required. It can be installed from the App Store.
To write React Native apps for Android, you will need to install the Android SDK (and an Android emulator if you want to work on your app without having to use a physical device). See Android setup guide for instructions on how to set up your Android environment.
NOTE: There is experimental Windows and Linux support for Android development.
To run the iOS app:
$ cd AwesomeProjectios/AwesomeProject.xcodeproj and hit run in Xcode.index.ios.js in your text editor of choice and edit some lines.Note: If you are using an iOS device, see the Running on iOS Device page.
To run the Android app:
$ cd AwesomeProject$ react-native run-androidindex.android.js in your text editor of choice and edit some lines.adb logcat *:S ReactNative:V ReactNativeJS:V in a terminal to see your app's logsNote: If you are using an Android device, see the Running on Android Device page.
Congratulations! You've successfully run and modified your first React Native app.
If you run into any issues getting started, see the troubleshooting page.
If you already have a (iOS-only) React Native project and want to add Android support, you need to execute the following commands in your existing project directory:
react-native dependency in your package.json file to the latest version$ npm install$ react-native androidGetting Started # | Edit on GitHub |
nvm install node && nvm alias default node, which installs the latest version of Node.js and sets up your terminal so you can run it by typing node. With nvm you can install multiple versions of Node.js and easily switch between them.brew install watchman. We recommend installing watchman, otherwise you might hit a node file watching bug.brew install flow, if you want to use flow.We recommend periodically running brew update && brew upgrade to keep your programs up-to-date.
Xcode 7.0 or higher is required. It can be installed from the App Store.
To write React Native apps for Android, you will need to install the Android SDK (and an Android emulator if you want to work on your app without having to use a physical device). See Android setup guide for instructions on how to set up your Android environment.
NOTE: There is experimental Windows and Linux support for Android development.
Install the React Native command line tools:
NOTE: If you see the error, EACCES: permission denied, please run the command: sudo npm install -g react-native-cli.
Create a React Native project:
To run the iOS app:
$ cd AwesomeProjectios/AwesomeProject.xcodeproj and hit run in Xcode.index.ios.js in your text editor of choice and edit some lines.Note: If you are using an iOS device, see the Running on iOS Device page.
To run the Android app:
$ cd AwesomeProject$ react-native run-androidindex.android.js in your text editor of choice and edit some lines.adb logcat *:S ReactNative:V ReactNativeJS:V in a terminal to see your app's logsNote: If you are using an Android device, see the Running on Android Device page.
Congratulations! You've successfully run and modified your first React Native app.
If you run into any issues getting started, see the troubleshooting page.
If you already have a (iOS-only) React Native project and want to add Android support, you need to execute the following commands in your existing project directory:
react-native dependency in your package.json file to the latest version$ npm install$ react-native androidImage # | Edit on GitHub |
A React component for displaying different types of images, +
Image # | Edit on GitHub |
A React component for displaying different types of images, including network images, static resources, temporary local images, and images from local disk, such as the camera roll.
Example usage:
Example usage:
Invoked on mount and layout changes with
-{nativeEvent: {layout: {x, y, width, height}}}.
Invoked when load completes successfully
Invoked when load either succeeds or fails
Invoked on load start
Determines how to resize the image when the frame doesn't match the raw +},
Invoked on mount and layout changes with
+{nativeEvent: {layout: {x, y, width, height}}}.
Invoked when load completes successfully
Invoked when load either succeeds or fails
Invoked on load start
Determines how to resize the image when the frame doesn't match the raw image dimensions.
'cover': Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
'contain': Scale the image uniformly (maintain the image's aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
'stretch': Scale width and height independently, This may change the -aspect ratio of the src.
uri is a string representing the resource identifier for the image, which
+aspect ratio of the src.
uri is a string representing the resource identifier for the image, which
could be an http address, a local file path, or the name of a static image
-resource (which should be wrapped in the require('./path/to/image.png') function).
When the image has rounded corners, specifying an overlayColor will
+resource (which should be wrapped in the require('./path/to/image.png') function).
When the image has rounded corners, specifying an overlayColor will cause the remaining space in the corners to be filled with a solid color. This is useful in cases which are not supported by the Android implementation of rounded corners: @@ -30,14 +30,14 @@ implementation of rounded corners: - Animated GIFs
A typical way to use this prop is with images displayed on a solid
background and setting the overlayColor to the same color
as the background.
For details of how this works under the hood, see -http://frescolib.org/docs/rounded-corners-and-circles.html
iOS-Specific style to "tint" an image. -Changes the color of all the non-transparent pixels to the tintColor.
A unique identifier for this element to be used in UI Automation -testing scripts.
The text that's read by the screen reader when the user interacts with -the image.
When true, indicates the image is an accessibility element.
When the image is resized, the corners of the size specified +http://frescolib.org/docs/rounded-corners-and-circles.html
iOS-Specific style to "tint" an image. +Changes the color of all the non-transparent pixels to the tintColor.
A unique identifier for this element to be used in UI Automation +testing scripts.
The text that's read by the screen reader when the user interacts with +the image.
When true, indicates the image is an accessibility element.
When the image is resized, the corners of the size specified by capInsets will stay a fixed size, but the center content and borders of the image will be stretched. This is useful for creating resizable rounded buttons, shadows, and other resizable assets. More info on -Apple documentation
A static image to display while loading the image source.
Invoked on load error with {nativeEvent: {error}}
Invoked on download progress with {nativeEvent: {loaded, total}}
Examples # | Edit on GitHub |
A static image to display while loading the image source.
Invoked on load error with {nativeEvent: {error}}
Invoked on download progress with {nativeEvent: {loaded, total}}
Examples # | Edit on GitHub |
Images # | Edit on GitHub |
As of 0.14 release, React Native provides a unified way of managing images in your iOS and Android apps. To add a static image to your app, place it somewhere in your source code tree and reference it like this:
The image name is resolved the same way JS modules are resolved. In the example above the packager will look for my-icon.png in the same folder as the component that requires it. Also if you have my-icon.ios.png and my-icon.android.png, the packager will pick the file depending on the platform you are running on.
You can also use @2x, @3x, etc. suffix in the file name to provide images for different screen densities. For example, if you have the following file structure:
Images # | Edit on GitHub |
As of 0.14 release, React Native provides a unified way of managing images in your iOS and Android apps. To add a static image to your app, place it somewhere in your source code tree and reference it like this:
The image name is resolved the same way JS modules are resolved. In the example above the packager will look for my-icon.png in the same folder as the component that requires it. Also if you have my-icon.ios.png and my-icon.android.png, the packager will pick the file depending on the platform you are running on.
You can also use @2x, @3x, etc. suffix in the file name to provide images for different screen densities. For example, if you have the following file structure:
Note that image sources required this way include size (width, height) info for the Image. If you need to scale the image dynamically (i.e. via flex), you may need to manually set { width: undefined, height: undefined } on the style attribute.
Available React Native 0.14+. If you've generated your project with 0.13 or earlier, read this. The new asset system relies on build hooks for Xcode and Gradle that are included in new projects generated with react-native init. If you generated your projects before that, you'll have to manually add them to your projects to use the new images asset system. See Upgrading for instructions on how to do this.
If you are building a hybrid app (some UIs in React Native, some UIs in platform code) you can still use images that are already bundled into the app (via Xcode asset catalogs or Android drawable folder):
Note that this approach provides no safety checks. It's up to you to guarantee that those images are available in the application. Also you have to specify image dimensions manually.
Many of the images you will display in your app will not be available at compile time, or you will want to load some dynamically to keep the binary size down. Unlike with static resources, you will need to manually specify the dimensions of your image.
Note that image sources required this way include size (width, height) info for the Image. If you need to scale the image dynamically (i.e. via flex), you may need to manually set { width: undefined, height: undefined } on the style attribute.
Available React Native 0.14+. If you've generated your project with 0.13 or earlier, read this. The new asset system relies on build hooks for Xcode and Gradle that are included in new projects generated with react-native init. If you generated your projects before that, you'll have to manually add them to your projects to use the new images asset system. See Upgrading for instructions on how to do this.
If you are building a hybrid app (some UIs in React Native, some UIs in platform code) you can still use images that are already bundled into the app (via Xcode asset catalogs or Android drawable folder):
Note that this approach provides no safety checks. It's up to you to guarantee that those images are available in the application. Also you have to specify image dimensions manually.
Many of the images you will display in your app will not be available at compile time, or you will want to load some dynamically to keep the binary size down. Unlike with static resources, you will need to manually specify the dimensions of your image.
See CameraRoll for an example of
-using local resources that are outside of Images.xcassets.
iOS saves multiple sizes for the same image in your Camera Roll, it is very important to pick the one that's as close as possible for performance reasons. You wouldn't want to use the full quality 3264x2448 image as source when displaying a 200x200 thumbnail. If there's an exact match, React Native will pick it, otherwise it's going to use the first one that's at least 50% bigger in order to avoid blur when resizing from a close size. All of this is done by default so you don't have to worry about writing the tedious (and error prone) code to do it yourself.
In the browser if you don't give a size to an image, the browser is going to render a 0x0 element, download the image, and then render the image based with the correct size. The big issue with this behavior is that your UI is going to jump all around as images load, this makes for a very bad user experience.
In React Native this behavior is intentionally not implemented. It is more work for the developer to know the dimensions (or aspect ratio) of the remote image in advance, but we believe that it leads to a better user experience. Static images loaded from the app bundle via the require('./my-icon.png') syntax can be automatically sized because their dimensions are available immediately at the time of mounting.
For example, the result of require('./my-icon.png') might be:
In React Native, one interesting decision is that the src attribute is named source and doesn't take a string but an object with an uri attribute.
On the infrastructure side, the reason is that it allows us to attach metadata to this object. For example if you are using require('./my-icon.png'), then we add information about its actual location and size (don't rely on this fact, it might change in the future!). This is also future proofing, for example we may want to support sprites at some point, instead of outputting {uri: ...}, we can output {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} and transparently support spriting on all the existing call sites.
On the user side, this lets you annotate the object with useful attributes such as the dimension of the image in order to compute the size it's going to be displayed in. Feel free to use it as your data structure to store more information about your image.
A common feature request from developers familiar with the web is background-image. To handle this use case, simply create a normal <Image> component and add whatever children to it you would like to layer on top of it.
See CameraRoll for an example of
+using local resources that are outside of Images.xcassets.
iOS saves multiple sizes for the same image in your Camera Roll, it is very important to pick the one that's as close as possible for performance reasons. You wouldn't want to use the full quality 3264x2448 image as source when displaying a 200x200 thumbnail. If there's an exact match, React Native will pick it, otherwise it's going to use the first one that's at least 50% bigger in order to avoid blur when resizing from a close size. All of this is done by default so you don't have to worry about writing the tedious (and error prone) code to do it yourself.
In the browser if you don't give a size to an image, the browser is going to render a 0x0 element, download the image, and then render the image based with the correct size. The big issue with this behavior is that your UI is going to jump all around as images load, this makes for a very bad user experience.
In React Native this behavior is intentionally not implemented. It is more work for the developer to know the dimensions (or aspect ratio) of the remote image in advance, but we believe that it leads to a better user experience. Static images loaded from the app bundle via the require('./my-icon.png') syntax can be automatically sized because their dimensions are available immediately at the time of mounting.
For example, the result of require('./my-icon.png') might be:
In React Native, one interesting decision is that the src attribute is named source and doesn't take a string but an object with an uri attribute.
On the infrastructure side, the reason is that it allows us to attach metadata to this object. For example if you are using require('./my-icon.png'), then we add information about its actual location and size (don't rely on this fact, it might change in the future!). This is also future proofing, for example we may want to support sprites at some point, instead of outputting {uri: ...}, we can output {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} and transparently support spriting on all the existing call sites.
On the user side, this lets you annotate the object with useful attributes such as the dimension of the image in order to compute the size it's going to be displayed in. Feel free to use it as your data structure to store more information about your image.
A common feature request from developers familiar with the web is background-image. To handle this use case, simply create a normal <Image> component and add whatever children to it you would like to layer on top of it.
Image decoding can take more than a frame-worth of time. This is one of the major source of frame drops on the web because decoding is done in the main thread. In React Native, image decoding is done in a different thread. In practice, you already need to handle the case when the image is not downloaded yet, so displaying the placeholder for a few more frames while it is decoding does not require any code change.
IntentAndroid # | Edit on GitHub |
NOTE: IntentAndroid is being deprecated. Use Linking instead.
IntentAndroid gives you a general interface to handle external links.
If your app was launched from an external url registered to your app you can +
IntentAndroid # | Edit on GitHub |
NOTE: IntentAndroid is being deprecated. Use Linking instead.
IntentAndroid gives you a general interface to handle external links.
If your app was launched from an external url registered to your app you can access and handle it from any component you want with
To start the corresponding activity for a link (web URL, email, contact etc.), call
If you want to check if any installed app can handle a given URL beforehand you can call
To start the corresponding activity for a link (web URL, email, contact etc.), call
If you want to check if any installed app can handle a given URL beforehand you can call
Starts a corresponding external activity for the given URL.
For example, if the URL is "https://www.facebook.com", the system browser will be opened, +});
Starts a corresponding external activity for the given URL.
For example, if the URL is "https://www.facebook.com", the system browser will be opened, or the "choose application" dialog will be shown.
You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact, or any other URL that can be opened with {@code Intent.ACTION_VIEW}.
NOTE: This method will fail if the system doesn't know how to open the specified URL. -If you're passing in a non-http(s) URL, it's best to check {@code canOpenURL} first.
NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
@deprecated
Determine whether or not an installed app can handle a given URL.
You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact, -or any other URL that can be opened with {@code Intent.ACTION_VIEW}.
NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
@param URL the URL to open
@deprecated
If the app launch was triggered by an app link with {@code Intent.ACTION_VIEW},
-it will give the link url, otherwise it will give null
Refer http://developer.android.com/training/app-indexing/deep-linking.html#handling-intents
@deprecated
Examples # | Edit on GitHub |
NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
@deprecated
Determine whether or not an installed app can handle a given URL.
You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact, +or any other URL that can be opened with {@code Intent.ACTION_VIEW}.
NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
@param URL the URL to open
@deprecated
If the app launch was triggered by an app link with {@code Intent.ACTION_VIEW},
+it will give the link url, otherwise it will give null
Refer http://developer.android.com/training/app-indexing/deep-linking.html#handling-intents
@deprecated
Examples # | Edit on GitHub |
nullRefer }, }); -module.exports = IntentAndroidExample;
InteractionManager # | Edit on GitHub |
InteractionManager allows long-running work to be scheduled after any +
InteractionManager # | Edit on GitHub |
InteractionManager allows long-running work to be scheduled after any interactions/animations have completed. In particular, this allows JavaScript animations to run smoothly.
Applications can schedule tasks to run after interactions with the following:
By default, queued tasks are executed together in a loop in one tasks will only be executed until the deadline (in terms of js event loop run time) approaches, at which point execution will yield via setTimeout, allowing events such as touches to start interactions and block queued tasks -from executing, making apps more responsive.
Schedule a function to run after all interactions have completed.
Notify manager that an interaction has started.
Notify manager that an interaction has completed.
A positive number will use setTimeout to schedule any tasks after the +from executing, making apps more responsive.
Schedule a function to run after all interactions have completed.
Notify manager that an interaction has started.
Notify manager that an interaction has completed.
A positive number will use setTimeout to schedule any tasks after the eventLoopRunningTime hits the deadline value, otherwise all tasks will be -executed in one setImmediate batch (default).
JavaScript Environment # | Edit on GitHub |
When using React Native, you're going to be running your JavaScript code in two environments:
While both environments are very similar, you may end up hitting some inconsistencies. We're likely going to experiment with other JS engines in the future, so it's best to avoid relying on specifics of any runtime.
Syntax transformers make writing code more enjoyable by allowing you to use new JavaScript syntax without having to wait for support on all interpreters.
As of version 0.5.0, React Native ships with the Babel JavaScript compiler. Check Babel documentation on its supported transformations for more details.
Here's a full list of React Native's enabled transformations.
ES5
promise.catch(function() { });ES6
<C onPress={() => this.setState({pressed: true})}let greeting = 'hi';Math.max(...array);class C extends React.Component { render() { return <View />; } }const answer = 42;var {isActive, style} = this.props;import React, { Component } from 'react-native';var key = 'abc'; var obj = {[key]: 10};var obj = { method() { return 10; } };var name = 'vjeux'; var obj = { name };function(type, ...args) { }var who = 'world'; var str = `Hello ${who}`;ES7
var extended = { ...obj, a: 10 };function f(a, b, c,) { }async function doStuffAsync() { const foo = await doOtherStuffAsync(); };JavaScript Environment # | Edit on GitHub |
When using React Native, you're going to be running your JavaScript code in two environments:
While both environments are very similar, you may end up hitting some inconsistencies. We're likely going to experiment with other JS engines in the future, so it's best to avoid relying on specifics of any runtime.
Syntax transformers make writing code more enjoyable by allowing you to use new JavaScript syntax without having to wait for support on all interpreters.
As of version 0.5.0, React Native ships with the Babel JavaScript compiler. Check Babel documentation on its supported transformations for more details.
Here's a full list of React Native's enabled transformations.
ES5
promise.catch(function() { });ES6
<C onPress={() => this.setState({pressed: true})}let greeting = 'hi';Math.max(...array);class C extends React.Component { render() { return <View />; } }const answer = 42;var {isActive, style} = this.props;for (var num of [1, 2, 3]) {}import React, { Component } from 'react-native';var key = 'abc'; var obj = {[key]: 10};var obj = { method() { return 10; } };var name = 'vjeux'; var obj = { name };function(type, ...args) { }var who = 'world'; var str = `Hello ${who}`;ES7
var extended = { ...obj, a: 10 };function f(a, b, c,) { }async function doStuffAsync() { const foo = await doOtherStuffAsync(); };Specific
Many standards functions are also available on all the supported JavaScript runtimes.
Browser
ES6
ES7
Specific
__DEV__Known Issues # | Edit on GitHub |
It's currently not possible to use the "React" tab in the devtools to inspect app widgets. This is due to a change in how the application scripts are evaluated in the devtools plugin; they are now run inside a Web Worker, and the plugin is unaware of this and so unable to communicate properly with React Native.
However, you can still use the Console feature of the devtools, and debugging JavaScript with breakpoints works too. To use the console, make sure to select the ⚙debuggerWorker.js entry in the devtools dropdown that by default is set to <top frame>.
This is an initial release of React Native Android and therefore not all of the views present on iOS are released on Android. We are very much interested in the communities' feedback on the next set of modules and views for Open Source. Not all native views between iOS and Android have a 100% equivalent representation, here it will be necessary to use a counterpart eg using ProgressBar on Android in place of ActivityIndicator on iOS.
Our provisional plan for common views and modules includes:
Known Issues # | Edit on GitHub |
It's currently not possible to use the "React" tab in the devtools to inspect app widgets. This is due to a change in how the application scripts are evaluated in the devtools plugin; they are now run inside a Web Worker, and the plugin is unaware of this and so unable to communicate properly with React Native.
However, you can still use the Console feature of the devtools, and debugging JavaScript with breakpoints works too. To use the console, make sure to select the ⚙debuggerWorker.js entry in the devtools dropdown that by default is set to <top frame>.
This is an initial release of React Native Android and therefore not all of the views present on iOS are released on Android. We are very much interested in the communities' feedback on the next set of modules and views for Open Source. Not all native views between iOS and Android have a 100% equivalent representation, here it will be necessary to use a counterpart eg using ProgressBar on Android in place of ActivityIndicator on iOS.
Our provisional plan for common views and modules includes:
There are properties that work on one platform only, either because they can inherently only be supported on that platform or because they haven't been implemented on the other platforms yet. All of these are annotated with @platform in JS docs and have a small badge next to them on the website. See e.g. Image.
There are known cases where the APIs could be made more consistent across iOS and Android:
<ViewPagerAndroid> and <ScrollView pagingEnabled={true}> on iOS do a similar thing. We might want to unify them to <ViewPager>.ActivityIndicator could render a native spinning indicator on both platforms (currently this is done using ActivityIndicatorIOS on iOS and ProgressBarAndroid on Android).ProgressBar could render a horizontal progress bar on both platforms (on iOS this is ProgressViewIOS, on Android it's ProgressBarAndroid).There are many awesome 3rd-party modules: JS.coach
Adding these to your apps should be made simpler. Here's an example how this is done currently.
overflow style property defaults to hidden and cannot be changed on Android #This is a result of how Android rendering works. This feature is not being worked on as it would be a significant undertaking and there are many more important tasks.
Another issue with overflow: 'hidden' on Android: a view is not clipped by the parent's borderRadius even if the parent has overflow: 'hidden' enabled – the corners of the inner view will be visible outside of the rounded corners. This is only on Android; it works as expected on iOS. See a demo of the bug and the corresponding issue.
The shadow* view styles apply on iOS, and the elevation view prop is available on Android. Setting elevation on Android is equivalent to using the native elevation API, and has the same limitations (most significantly, it only works on Android 5.0+). Setting elevation on Android also affects the z-order for overlapping views.
The open source version of React Native doesn't yet support the Android M permission model.
An optimization feature of the Android version of React Native is for views which only contribute to the layout to not have a native view, only their layout properties are propagated to their children views. This optimization is to provide stability in deep view hierarchies for React Native and is therefore enabled by default. Should you depend on a view being present or internal tests incorrectly detect a view is layout only it will be necessary to turn off this behavior. To do this, set collapsable to false as in this example:
There are properties that work on one platform only, either because they can inherently only be supported on that platform or because they haven't been implemented on the other platforms yet. All of these are annotated with @platform in JS docs and have a small badge next to them on the website. See e.g. Image.
There are known cases where the APIs could be made more consistent across iOS and Android:
<ViewPagerAndroid> and <ScrollView pagingEnabled={true}> on iOS do a similar thing. We might want to unify them to <ViewPager>.ActivityIndicator could render a native spinning indicator on both platforms (currently this is done using ActivityIndicatorIOS on iOS and ProgressBarAndroid on Android).ProgressBar could render a horizontal progress bar on both platforms (on iOS this is ProgressViewIOS, on Android it's ProgressBarAndroid).There are many awesome 3rd-party modules: JS.coach
Adding these to your apps should be made simpler. Here's an example how this is done currently.
overflow style property defaults to hidden and cannot be changed on Android #This is a result of how Android rendering works. This feature is not being worked on as it would be a significant undertaking and there are many more important tasks.
Another issue with overflow: 'hidden' on Android: a view is not clipped by the parent's borderRadius even if the parent has overflow: 'hidden' enabled – the corners of the inner view will be visible outside of the rounded corners. This is only on Android; it works as expected on iOS. See a demo of the bug and the corresponding issue.
The shadow* view styles apply on iOS, and the elevation view prop is available on Android. Setting elevation on Android is equivalent to using the native elevation API, and has the same limitations (most significantly, it only works on Android 5.0+). Setting elevation on Android also affects the z-order for overlapping views.
The open source version of React Native doesn't yet support the Android M permission model.
An optimization feature of the Android version of React Native is for views which only contribute to the layout to not have a native view, only their layout properties are propagated to their children views. This optimization is to provide stability in deep view hierarchies for React Native and is therefore enabled by default. Should you depend on a view being present or internal tests incorrectly detect a view is layout only it will be necessary to turn off this behavior. To do this, set collapsable to false as in this example:
React Native Android depends on Fresco for loading and displaying images. Currently we have disabled downsampling because it is experimental, so you may run into memory issues when loading large PNG images.
Try running react-native init with --verbose and see #2797 for common causes.
The text input has by default a border at the bottom of its view. This border has its padding set by the background image provided by the system, and it cannot be changed. Solutions to avoid this is to either not set height explicitly, case in which the system will take care of displaying the border in the correct position, or to not display the border by setting underlineColor to transparent.
LayoutAnimation # | Edit on GitHub |
Automatically animates views to their new positions when the +
LayoutAnimation # | Edit on GitHub |
Automatically animates views to their new positions when the next layout happens.
A common way to use this API is to call LayoutAnimation.configureNext
-before calling setState.
Schedules an animation to happen on the next layout.
@param config Specifies animation properties:
duration in millisecondscreate, config for animating in new views (see Anim type)update, config for animating views that have been updated
+before calling setState.Schedules an animation to happen on the next layout.
@param config Specifies animation properties:
duration in millisecondscreate, config for animating in new views (see Anim type)update, config for animating views that have been updated
(see Anim type)@param onAnimationDidEnd Called when the animation finished. Only supported on iOS. -@param onError Called on error. Only supported on iOS.
Helper for creating a config for configureNext.
Linking Libraries # | Edit on GitHub |
Not every app uses all the native capabilities, and including the code to support +
Linking Libraries # | Edit on GitHub |
Not every app uses all the native capabilities, and including the code to support all those features would impact the binary size... But we still want to make it easy to add these features whenever you need them.
With that in mind we exposed many of these features as independent static libraries.
For most of the libs it will be as simple as dragging two files, sometimes a third step will be necessary, but no more than that.
All the libraries we ship with React Native live on the Libraries folder in
the root of the repository. Some of them are pure JavaScript, and you only need
to require it. Other libraries also rely on some native code, in that case
you'll have to add these files to your app, otherwise the app will throw an
-error as soon as you try to use the library.
"rnpm" is a community project that allows linking of native dependencies automatically:
Install rnpm:
Note: rnpm requires node version 4.1 or higher
Install a library with native dependencies:
Note: --save or --save-dev flag is very important for this step. rnpm will link
-your libs based on dependencies and devDependencies in your package.json file.
Link your native dependencies:
Done! All libraries with a native dependencies should be successfully linked to your iOS/Android project.
If the library has native code, there must be a .xcodeproj file inside it's
+error as soon as you try to use the library.
"rnpm" is a community project that allows linking of native dependencies automatically:
Install rnpm:
Note: rnpm requires node version 4.1 or higher
Install a library with native dependencies:
Note: --save or --save-dev flag is very important for this step. rnpm will link
+your libs based on dependencies and devDependencies in your package.json file.
Link your native dependencies:
Done! All libraries with a native dependencies should be successfully linked to your iOS/Android project.
If the library has native code, there must be a .xcodeproj file inside it's
folder.
Drag this file to your project on Xcode (usually under the Libraries group
-on Xcode);

Click on your main project file (the one that represents the .xcodeproj)
+on Xcode);

Click on your main project file (the one that represents the .xcodeproj)
select Build Phases and drag the static library from the Products folder
-inside the Library you are importing to Link Binary With Libraries

Not every library will need this step, what you need to consider is:
Do I need to know the contents of the library at compile time?
What that means is, are you using this library on the native side or only in
+inside the Library you are importing to Link Binary With Libraries

Not every library will need this step, what you need to consider is:
Do I need to know the contents of the library at compile time?
What that means is, are you using this library on the native side or only in JavaScript? If you are only using it in JavaScript, you are good to go!
This step is not necessary for libraries that we ship with React Native with the
exception of PushNotificationIOS and LinkingIOS.
In the case of the PushNotificationIOS for example, you have to call a method
on the library from your AppDelegate every time a new push notification is
@@ -19,7 +19,7 @@ received.
For that we need to know the library's headers. To achieve
to your project's file, select Build Settings and search for Header Search
Paths. There you should include the path to your library (if it has relevant
files on subdirectories remember to make it recursive, like React on the
-example).

Linking # | Edit on GitHub |
Linking gives you a general interface to interact with both incoming
-and outgoing app links.
If your app was launched from an external url registered to your app you can +
Linking # | Edit on GitHub |
Linking gives you a general interface to interact with both incoming
+and outgoing app links.
If your app was launched from an external url registered to your app you can access and handle it from any component you want with
NOTE: For instructions on how to add support for deep linking on Android, refer Enabling Deep Links for App Content - Add Intent Filters for Your Deep Links.
NOTE: For iOS, in case you also want to listen to incoming app links during your app's
-execution you'll need to add the following lines to you *AppDelegate.m:
*AppDelegate.m:*AppDelegate.
- (BOOL)application:(UIApplication *)application continueUserActivity:(NSUserActivity *)userActivity
restorationHandler:(void (^)(NSArray * _Nullable))restorationHandler
{
- return [LinkingManager application:application
+ return [RCTLinkingManager application:application
continueUserActivity:userActivity
restorationHandler:restorationHandler];
}And then on your React component you'll be able to listen to the events on
@@ -31,18 +33,18 @@ execution you'll need to add the following lines to you *AppDelegate.
},
_handleOpenURL(event) {
console.log(event.url);
-}
Note that this is only supported on iOS.
To start the corresponding activity for a link (web URL, email, contact etc.), call
If you want to check if any installed app can handle a given URL beforehand you can call
Note that this is only supported on iOS.
To start the corresponding activity for a link (web URL, email, contact etc.), call
If you want to check if any installed app can handle a given URL beforehand you can call
Add a handler to Linking changes by listening to the url event type
-and providing the handler
@platform ios
Remove a handler by passing the url event type and the handler
@platform ios
Try to open the given url with any of the installed apps.
You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact, +}).catch(err => console.error('An error occurred', err));
Add a handler to Linking changes by listening to the url event type
+and providing the handler
@platform ios
Remove a handler by passing the url event type and the handler
@platform ios
Try to open the given url with any of the installed apps.
You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386"), a contact, or any other URL that can be opened with the installed apps.
NOTE: This method will fail if the system doesn't know how to open the specified URL. -If you're passing in a non-http(s) URL, it's best to check {@code canOpenURL} first.
NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
Determine whether or not an installed app can handle a given URL.
NOTE: For web URLs, the protocol ("http://", "https://") must be set accordingly!
NOTE: As of iOS 9, your app needs to provide the LSApplicationQueriesSchemes key
-inside Info.plist.
@param URL the URL to open
If the app launch was triggered by an app link with,
-it will give the link url, otherwise it will give null
NOTE: To support deep linking on Android, refer http://developer.android.com/training/app-indexing/deep-linking.html#handling-intents
LinkingIOS # | Edit on GitHub |
NOTE: LinkingIOS is being deprecated. Use Linking instead.
LinkingIOS gives you a general interface to interact with both incoming
-and outgoing app links.
If your app was launched from an external url registered to your app you can +
LinkingIOS # | Edit on GitHub |
NOTE: LinkingIOS is being deprecated. Use Linking instead.
LinkingIOS gives you a general interface to interact with both incoming
+and outgoing app links.
If your app was launched from an external url registered to your app you can access and handle it from any component you want with
In case you also want to listen to incoming app links during your app's
@@ -26,17 +26,17 @@ execution you'll need to add the following lines to you *AppDelegate.
},
_handleOpenURL(event) {
console.log(event.url);
-}
To trigger an app link (browser, email or custom schemas), call
If you want to check if any installed app can handle a given URL beforehand, call
To trigger an app link (browser, email or custom schemas), call
If you want to check if any installed app can handle a given URL beforehand, call
Add a handler to LinkingIOS changes by listening to the url event type
-and providing the handler
@deprecated
Remove a handler by passing the url event type and the handler
@deprecated
Try to open the given url with any of the installed apps.
@deprecated
Determine whether or not an installed app can handle a given URL. +});
Add a handler to LinkingIOS changes by listening to the url event type
+and providing the handler
@deprecated
Remove a handler by passing the url event type and the handler
@deprecated
Try to open the given url with any of the installed apps.
@deprecated
Determine whether or not an installed app can handle a given URL.
The callback function will be called with bool supported as the only argument
NOTE: As of iOS 9, your app needs to provide the LSApplicationQueriesSchemes key
-inside Info.plist.
@deprecated
If the app launch was triggered by an app link, it will pop the link url,
-otherwise it will return null
@deprecated
Linux and Windows Support # | Edit on GitHub |
NOTE: This guide focuses on Android development. You'll need a Mac to build iOS apps.
As React Native on iOS requires a Mac and most of the engineers at Facebook and contributors use Macs, support for OS X is a top priority. However, we would like to support developers using Linux and Windows too. We believe we'll get the best Linux and Windows support from people using these operating systems on a daily basis.
Therefore, Linux and Windows support for the development environment is an ongoing community responsibility. This can mean filing issues and submitting PRs, and we'll help review and merge them. We are looking forward to your contributions and appreciate your patience.
As of version 0.14 Android development with React native is mostly possible on Linux and Windows. You'll need to install Node.js 4.0 or newer. On Linux we recommend installing watchman, otherwise you might hit a node file watching bug.
On Windows the packager won't be started automatically when you run react-native run-android. You can start it manually using:
If you hit a ERROR Watcher took too long to load on Windows, try increasing the timeout in this file (under your node_modules/react-native).
Linux and Windows Support # | Edit on GitHub |
NOTE: This guide focuses on Android development. You'll need a Mac to build iOS apps.
As React Native on iOS requires a Mac and most of the engineers at Facebook and contributors use Macs, support for OS X is a top priority. However, we would like to support developers using Linux and Windows too. We believe we'll get the best Linux and Windows support from people using these operating systems on a daily basis.
Therefore, Linux and Windows support for the development environment is an ongoing community responsibility. This can mean filing issues and submitting PRs, and we'll help review and merge them. We are looking forward to your contributions and appreciate your patience.
As of version 0.14 Android development with React native is mostly possible on Linux and Windows. You'll need to install Node.js 4.0 or newer. On Linux we recommend installing watchman, otherwise you might hit a node file watching bug.
On Windows the packager won't be started automatically when you run react-native run-android. You can start it manually using:
If you hit a ERROR Watcher took too long to load on Windows, try increasing the timeout in this file (under your node_modules/react-native).
ListView # | Edit on GitHub |
ListView - A core component designed for efficient display of vertically +
ListView # | Edit on GitHub |
ListView - A core component designed for efficient display of vertically
scrolling lists of changing data. The minimal API is to create a
ListView.DataSource, populate it with a simple array of data blobs, and
instantiate a ListView component with that data source and a renderRow
@@ -28,39 +28,43 @@ data source tells the ListView if it needs to re-render a row because the
source data has changed - see ListViewDataSource for more details.
Rate-limited row rendering - By default, only one row is rendered per
event-loop (customizable with the pageSize prop). This breaks up the
work into smaller chunks to reduce the chance of dropping frames while
-rendering rows.
How many rows to render on initial component mount. Use this to make +rendering rows.
How many rows to render on initial component mount. Use this to make it so that the first screen worth of data appears at one time instead of -over the course of multiple frames.
(visibleRows, changedRows) => void
Called when the set of visible rows changes. visibleRows maps
+over the course of multiple frames.
(visibleRows, changedRows) => void
Called when the set of visible rows changes. visibleRows maps
{ sectionID: { rowID: true }} for all the visible rows, and
changedRows maps { sectionID: { rowID: true | false }} for the rows
that have changed their visibility, with true indicating visible, and
-false indicating the view has moved out of view.
Called when all rows have been rendered and the list has been scrolled +false indicating the view has moved out of view.
Called when all rows have been rendered and the list has been scrolled to within onEndReachedThreshold of the bottom. The native scroll -event is provided.
Threshold in pixels for onEndReached.
Number of rows to render per event loop.
A performance optimization for improving scroll perf of +event is provided.
Threshold in pixels (virtual, not physical) for calling onEndReached.
Number of rows to render per event loop. Note: if your 'rows' are actually +cells, i.e. they don't span the full width of your view (as in the +ListViewGridLayoutExample), you should set the pageSize to be a multiple +of the number of cells per row, otherwise you're likely to see gaps at +the edge of the ListView as new pages are loaded.
A performance optimization for improving scroll perf of large lists, used in conjunction with overflow: 'hidden' on the row -containers. This is enabled by default.
() => renderable
The header and footer are always rendered (if these props are provided) +containers. This is enabled by default.
() => renderable
The header and footer are always rendered (if these props are provided) on every render pass. If they are expensive to re-render, wrap them in StaticContainer or other mechanism as appropriate. Footer is always -at the bottom of the list, and header at the top, on every render pass.
(rowData, sectionID, rowID, highlightRow) => renderable
Takes a data entry from the data source and its ids and should return +at the bottom of the list, and header at the top, on every render pass.
(rowData, sectionID, rowID, highlightRow) => renderable
Takes a data entry from the data source and its ids and should return a renderable component to be rendered as the row. By default the data is exactly what was put into the data source, but it's also possible to provide custom extractors. ListView can be notified when a row is being highlighted by calling highlightRow function. The separators above and below will be hidden when a row is highlighted. The highlighted state of -a row can be reset by calling highlightRow(null).
(props) => renderable
A function that returns the scrollable component in which the list rows -are rendered. Defaults to returning a ScrollView with the given props.
(sectionData, sectionID) => renderable
If provided, a sticky header is rendered for this section. The sticky +a row can be reset by calling highlightRow(null).
(props) => renderable
A function that returns the scrollable component in which the list rows +are rendered. Defaults to returning a ScrollView with the given props.
(sectionData, sectionID) => renderable
If provided, a sticky header is rendered for this section. The sticky behavior means that it will scroll with the content at the top of the section until it reaches the top of the screen, at which point it will stick to the top until it is pushed off the screen by the next section -header.
(sectionID, rowID, adjacentRowHighlighted) => renderable
If provided, a renderable component to be rendered as the separator +header.
(sectionID, rowID, adjacentRowHighlighted) => renderable
If provided, a renderable component to be rendered as the separator below each row but not the last row if there is a section header below. Take a sectionID and rowID of the row above and whether its adjacent row -is highlighted.
How early to start rendering rows before they come on screen, in -pixels.
An array of child indices determining which children get docked to the +is highlighted.
How early to start rendering rows before they come on screen, in +pixels.
An array of child indices determining which children get docked to the
top of the screen when scrolling. For example, passing
stickyHeaderIndices={[0]} will cause the first child to be fixed to the
top of the scroll view. This property is not supported in conjunction
-with horizontal={true}.
Examples # | Edit on GitHub |
horizontal={true}.Examples # | Edit on GitHub |
horizontal={true}.MapView # | Edit on GitHub |
Deprecated. Use annotation onFocus and onBlur instead.
Callback that is called continuously when the user is dragging the map.
Callback that is called once, when the user is done moving the map.
When this property is set to true and a valid camera is associated
+
MapView # | Edit on GitHub |
Deprecated. Use annotation onFocus and onBlur instead.
Callback that is called continuously when the user is dragging the map.
Callback that is called once, when the user is done moving the map.
When this property is set to true and a valid camera is associated
with the map, the camera’s pitch angle is used to tilt the plane
of the map. When this property is set to false, the camera’s pitch
angle is ignored and the map is always displayed as if the user
-is looking straight down onto it.
The region to be displayed by the map.
The region is defined by the center coordinates and the span of -coordinates to display.
When this property is set to true and a valid camera is associated with
+is looking straight down onto it.
The region to be displayed by the map.
The region is defined by the center coordinates and the span of +coordinates to display.
When this property is set to true and a valid camera is associated with
the map, the camera’s heading angle is used to rotate the plane of the
map around its center point. When this property is set to false, the
camera’s heading angle is ignored and the map is always oriented so
-that true north is situated at the top of the map view
If false the user won't be able to change the map region being displayed.
-Default value is true.
If true the app will ask for the user's location and display it on
+that true north is situated at the top of the map view
If false the user won't be able to change the map region being displayed.
+Default value is true.
If true the app will ask for the user's location and display it on
the map. Default value is false.
NOTE: on iOS, you need to add the NSLocationWhenInUseUsageDescription
-key in Info.plist to enable geolocation, otherwise it will fail silently.
Used to style and layout the MapView. See StyleSheet.js and
-ViewStylePropTypes.js for more info.
If false the user won't be able to pinch/zoom the map.
-Default value is true.
Used to style and layout the MapView. See StyleSheet.js and
+ViewStylePropTypes.js for more info.
If false the user won't be able to pinch/zoom the map.
+Default value is true.
true.Map annotations with title/subtitle.
If true the map will follow the user's location whenever it changes.
+)}] #
Map annotations with title/subtitle.
If true the map will follow the user's location whenever it changes.
Note that this has no effect unless showsUserLocation is enabled.
-Default value is true.
Insets for the map's legal label, originally at bottom left of the map.
-See EdgeInsetsPropType.js for more information.
The map type to be displayed.
Maximum size of area that can be displayed.
Minimum size of area that can be displayed.
Map overlays
If false compass won't be displayed on the map.
-Default value is true.
If false points of interest won't be displayed on the map.
-Default value is true.
Examples # | Edit on GitHub |
true.Insets for the map's legal label, originally at bottom left of the map.
+See EdgeInsetsPropType.js for more information.
The map type to be displayed.
Maximum size of area that can be displayed.
Minimum size of area that can be displayed.
Map overlays
If false compass won't be displayed on the map.
+Default value is true.
If false points of interest won't be displayed on the map.
+Default value is true.
Examples # | Edit on GitHub |
Modal # | Edit on GitHub |
A Modal component covers the native view (e.g. UIViewController, Activity) +
Modal # | Edit on GitHub |
A Modal component covers the native view (e.g. UIViewController, Activity) that contains the React Native root.
Use Modal in hybrid apps that embed React Native; Modal allows the portion of your app written in React Native to present content above the enclosing native view hierarchy.
In apps written with React Native from the root view down, you should use Navigator instead of Modal. With a top-level Navigator, you have more control over how to present the modal scene over the rest of your app by using the -configureScene property.
This component is only available in iOS at this time.
Examples # | Edit on GitHub |
This component is only available in iOS at this time.
Examples # | Edit on GitHub |
Native UI Components # | Edit on GitHub |
There are tons of native UI widgets out there ready to be used in the latest apps - some of them are part of the platform, others are available as third-party libraries, and still more might be in use in your very own portfolio. React Native has several of the most critical platform components already wrapped, like ScrollView and TextInput, but not all of them, and certainly not ones you might have written yourself for a previous app. Fortunately, it's quite easy to wrap up these existing components for seamless integration with your React Native application.
Like the native module guide, this too is a more advanced guide that assumes you are somewhat familiar with Android SDK programming. This guide will show you how to build a native UI component, walking you through the implementation of a subset of the existing ImageViewcomponent available in the core React Native library.
For this example we are going to walk through the implementation requirements to allow the use of ImageViews in JavaScript.
Native views are created and manipulated by extending ViewManager or more commonly SimpleViewManager . A SimpleViewManager is convenient in this case because it applies common properties such as background color, opacity, and Flexbox layout.
These subclasses are essentially singletons - only one instance of each is created by the bridge. They vend native views to the NativeViewHierarchyManager, which delegates back to them to set and update the properties of the views as necessary. The ViewManagers are also typically the delegates for the views, sending events back to JavaScript via the bridge.
Vending a view is simple:
createViewInstance method@ReactProp (or @ReactPropGroup) annotationcreateViewManagers of the applications package.ViewManager subclass #In this example we create view manager class ReactImageManager that extends SimpleViewManager of type ReactImageView. ReactImageView is the type of object managed by the manager, this will be the custom native view. Name returned by getName is used to reference the native view type from JavaScript.
Native UI Components # | Edit on GitHub |
There are tons of native UI widgets out there ready to be used in the latest apps - some of them are part of the platform, others are available as third-party libraries, and still more might be in use in your very own portfolio. React Native has several of the most critical platform components already wrapped, like ScrollView and TextInput, but not all of them, and certainly not ones you might have written yourself for a previous app. Fortunately, it's quite easy to wrap up these existing components for seamless integration with your React Native application.
Like the native module guide, this too is a more advanced guide that assumes you are somewhat familiar with Android SDK programming. This guide will show you how to build a native UI component, walking you through the implementation of a subset of the existing ImageViewcomponent available in the core React Native library.
For this example we are going to walk through the implementation requirements to allow the use of ImageViews in JavaScript.
Native views are created and manipulated by extending ViewManager or more commonly SimpleViewManager . A SimpleViewManager is convenient in this case because it applies common properties such as background color, opacity, and Flexbox layout.
These subclasses are essentially singletons - only one instance of each is created by the bridge. They vend native views to the NativeViewHierarchyManager, which delegates back to them to set and update the properties of the views as necessary. The ViewManagers are also typically the delegates for the views, sending events back to JavaScript via the bridge.
Vending a view is simple:
createViewInstance method@ReactProp (or @ReactPropGroup) annotationcreateViewManagers of the applications package.ViewManager subclass #In this example we create view manager class ReactImageManager that extends SimpleViewManager of type ReactImageView. ReactImageView is the type of object managed by the manager, this will be the custom native view. Name returned by getName is used to reference the native view type from JavaScript.
createViewInstance #Views are created in the createViewInstance method, the view should initialize itself in its default state, any properties will be set via a follow up call to updateView.
createViewInstance #Views are created in the createViewInstance method, the view should initialize itself in its default state, any properties will be set via a follow up call to updateView.
@ReactProp (or @ReactPropGroup) annotation #Properties that are to be reflected in JavaScript needs to be exposed as setter method annotated with @ReactProp (or @ReactPropGroup). Setter method should take view to be updated (of the current view type) as a first argument and property value as a second argument. Setter should be declared as a void method and should be public. Property type sent to JS is determined automatically based on the type of value argument of the setter. The following type of values are currently supported: boolean, int, float, double, String, Boolean, Integer, ReadableArray, ReadableMap.
Annotation @ReactProp has one obligatory argument name of type String. Name assigned to the @ReactProp annotation linked to the setter method is used to reference the property on JS side.
Except from name, @ReactProp annotation may take following optional arguments: defaultBoolean, defaultInt, defaultFloat. Those arguments should be of the corresponding primitive type (accordingly boolean, int, float) and the value provided will be passed to the setter method in case when the property that the setter is referencing has been removed from the component. Note that "default" values are only provided for primitive types, in case when setter is of some complex type, null will be provided as a default value in case when corresponding property gets removed.
Setter declaration requirements for methods annotated with @ReactPropGroup are different than for @ReactProp, please refer to the @ReactPropGroup annotation class docs for more information about it.
IMPORTANT! in ReactJS updating the property value will result in setter method call. Note that one of the ways we can update component is by removing properties that has been set before. In that case setter method will be called as well to notify view manager that property has changed. In that case "default" value will be provided (for primitive types "default" can value can be specified using defaultBoolean, defaultFloat, etc. arguments of @ReactProp annotation, for complex types setter will be called with value set to null).
@ReactProp (or @ReactPropGroup) annotation #Properties that are to be reflected in JavaScript needs to be exposed as setter method annotated with @ReactProp (or @ReactPropGroup). Setter method should take view to be updated (of the current view type) as a first argument and property value as a second argument. Setter should be declared as a void method and should be public. Property type sent to JS is determined automatically based on the type of value argument of the setter. The following type of values are currently supported: boolean, int, float, double, String, Boolean, Integer, ReadableArray, ReadableMap.
Annotation @ReactProp has one obligatory argument name of type String. Name assigned to the @ReactProp annotation linked to the setter method is used to reference the property on JS side.
Except from name, @ReactProp annotation may take following optional arguments: defaultBoolean, defaultInt, defaultFloat. Those arguments should be of the corresponding primitive type (accordingly boolean, int, float) and the value provided will be passed to the setter method in case when the property that the setter is referencing has been removed from the component. Note that "default" values are only provided for primitive types, in case when setter is of some complex type, null will be provided as a default value in case when corresponding property gets removed.
Setter declaration requirements for methods annotated with @ReactPropGroup are different than for @ReactProp, please refer to the @ReactPropGroup annotation class docs for more information about it.
IMPORTANT! in ReactJS updating the property value will result in setter method call. Note that one of the ways we can update component is by removing properties that has been set before. In that case setter method will be called as well to notify view manager that property has changed. In that case "default" value will be provided (for primitive types "default" can value can be specified using defaultBoolean, defaultFloat, etc. arguments of @ReactProp annotation, for complex types setter will be called with value set to null).
ViewManager #The final Java step is to register the ViewManager to the application, this happens in a similar way to Native Modules, via the applications package member function createViewManagers.
ViewManager #The final Java step is to register the ViewManager to the application, this happens in a similar way to Native Modules, via the applications package member function createViewManagers.
The very final step is to create the JavaScript module that defines the interface layer between Java and JavaScript for the users of your new view. Much of the effort is handled by internal React code in Java and JavaScript and all that is left for you is to describe the propTypes.
The very final step is to create the JavaScript module that defines the interface layer between Java and JavaScript for the users of your new view. Much of the effort is handled by internal React code in Java and JavaScript and all that is left for you is to describe the propTypes.
requireNativeComponent commonly takes two parameters, the first is the name of the native view and the second is an object that describes the component interface. The component interface should declare a friendly name for use in debug messages and must declare the propTypes reflected by the Native View. The propTypes are used for checking the validity of a user's use of the native view. Note that if you need your JavaScript component to do more than just specify a name and propTypes, like do custom event handling, you can wrap the native component in a normal react component. In that case, you want to pass in the wrapper component instead of iface to requireNativeComponent. This is illustrated in the MyCustomView example below.
So now we know how to expose native view components that we can control easily from JS, but how do we deal with events from the user, like pinch-zooms or panning? When a native event occurs the native code should issue an event to the JavaScript representation of the View, and the two views are linked with the value returned from the getId() method.
requireNativeComponent commonly takes two parameters, the first is the name of the native view and the second is an object that describes the component interface. The component interface should declare a friendly name for use in debug messages and must declare the propTypes reflected by the Native View. The propTypes are used for checking the validity of a user's use of the native view. Note that if you need your JavaScript component to do more than just specify a name and propTypes, like do custom event handling, you can wrap the native component in a normal react component. In that case, you want to pass in the wrapper component instead of iface to requireNativeComponent. This is illustrated in the MyCustomView example below.
So now we know how to expose native view components that we can control easily from JS, but how do we deal with events from the user, like pinch-zooms or panning? When a native event occurs the native code should issue an event to the JavaScript representation of the View, and the two views are linked with the value returned from the getId() method.
Note the use of nativeOnly above. Sometimes you'll have some special properties that you need to expose for the native component, but don't actually want them as part of the API for the associated React component. For example, Switch has a custom onChange handler for the raw native event, and exposes an onValueChange handler property that is invoked with just the boolean value rather than the raw event (similar to onChangeMessage in the example above). Since you don't want these native only properties to be part of the API, you don't want to put them in propTypes, but if you don't you'll get an error. The solution is simply to call them out via the nativeOnly option.
Native UI Components # | Edit on GitHub |
There are tons of native UI widgets out there ready to be used in the latest apps - some of them are part of the platform, others are available as third-party libraries, and still more might be in use in your very own portfolio. React Native has several of the most critical platform components already wrapped, like ScrollView and TextInput, but not all of them, and certainly not ones you might have written yourself for a previous app. Fortunately, it's quite easy to wrap up these existing components for seamless integration with your React Native application.
Like the native module guide, this too is a more advanced guide that assumes you are somewhat familiar with iOS programming. This guide will show you how to build a native UI component, walking you through the implementation of a subset of the existing MapView component available in the core React Native library.
Let's say we want to add an interactive Map to our app - might as well use MKMapView, we just need to make it usable from JavaScript.
Native views are created and manipulated by subclasses of RCTViewManager. These subclasses are similar in function to view controllers, but are essentially singletons - only one instance of each is created by the bridge. They vend native views to the RCTUIManager, which delegates back to them to set and update the properties of the views as necessary. The RCTViewManagers are also typically the delegates for the views, sending events back to JavaScript via the bridge.
Vending a view is simple:
RCT_EXPORT_MODULE() marker macro.-(UIView *)view methodNative UI Components # | Edit on GitHub |
There are tons of native UI widgets out there ready to be used in the latest apps - some of them are part of the platform, others are available as third-party libraries, and still more might be in use in your very own portfolio. React Native has several of the most critical platform components already wrapped, like ScrollView and TextInput, but not all of them, and certainly not ones you might have written yourself for a previous app. Fortunately, it's quite easy to wrap up these existing components for seamless integration with your React Native application.
Like the native module guide, this too is a more advanced guide that assumes you are somewhat familiar with iOS programming. This guide will show you how to build a native UI component, walking you through the implementation of a subset of the existing MapView component available in the core React Native library.
Let's say we want to add an interactive Map to our app - might as well use MKMapView, we just need to make it usable from JavaScript.
Native views are created and manipulated by subclasses of RCTViewManager. These subclasses are similar in function to view controllers, but are essentially singletons - only one instance of each is created by the bridge. They vend native views to the RCTUIManager, which delegates back to them to set and update the properties of the views as necessary. The RCTViewManagers are also typically the delegates for the views, sending events back to JavaScript via the bridge.
Vending a view is simple:
RCT_EXPORT_MODULE() marker macro.-(UIView *)view methodThen you just need a little bit of JavaScript to make this a usable React component:
This is now a fully-functioning native map view component in JavaScript, complete with pinch-zoom and other native gesture support. We can't really control it from JavaScript yet, though :(
The first thing we can do to make this component more usable is to bridge over some native properties. Let's say we want to be able to disable pitch control and specify the visible region. Disabling pitch is a simple boolean, so we add this one line:
This is now a fully-functioning native map view component in JavaScript, complete with pinch-zoom and other native gesture support. We can't really control it from JavaScript yet, though :(
The first thing we can do to make this component more usable is to bridge over some native properties. Let's say we want to be able to disable pitch control and specify the visible region. Disabling pitch is a simple boolean, so we add this one line:
Note that we explicitly specify the type as BOOL - React Native uses RCTConvert under the hood to convert all sorts of different data types when talking over the bridge, and bad values will show convenient "RedBox" errors to let you know there is an issue ASAP. When things are straightforward like this, the whole implementation is taken care of for you by this macro.
Now to actually disable pitch, we set the property in JS:
This isn't very well documented though - in order to know what properties are available and what values they accept, the client of your new component needs to dig through the Objective-C code. To make this better, let's make a wrapper component and document the interface with React PropTypes:
Here you can see that the shape of the region is explicit in the JS documentation - ideally we could codegen some of this stuff, but that's not happening yet.
Sometimes you'll have some special properties that you need to expose for the native component, but don't actually want them as part of the API for the associated React component. For example, Switch has a custom onChange handler for the raw native event, and exposes an onValueChange handler property that is invoked with just the boolean value rather than the raw event. Since you don't want these native only properties to be part of the API, you don't want to put them in propTypes, but if you don't you'll get an error. The solution is simply to call them out via the nativeOnly option, e.g.
So now we have a native map component that we can control easily from JS, but how do we deal with events from the user, like pinch-zooms or panning to change the visible region? The key is to make the RCTMapManager a delegate for all the views it vends, and forward the events to JS via the event dispatcher. This looks like so (simplified from the full implementation):
So now we have a native map component that we can control easily from JS, but how do we deal with events from the user, like pinch-zooms or panning to change the visible region? The key is to make the RCTMapManager a delegate for all the views it vends, and forward the events to JS via the event dispatcher. This looks like so (simplified from the full implementation):
Since all our native react views are subclasses of UIView, most style attributes will work like you would expect out of the box. Some components will want a default style, however, for example UIDatePicker which is a fixed size. This default style is important for the layout algorithm to work as expected, but we also want to be able to override the default style when using the component. DatePickerIOS does this by wrapping the native component in an extra view, which has flexible styling, and using a fixed style (which is generated with constants passed in from native) on the inner native component:
Since all our native react views are subclasses of UIView, most style attributes will work like you would expect out of the box. Some components will want a default style, however, for example UIDatePicker which is a fixed size. This default style is important for the layout algorithm to work as expected, but we also want to be able to override the default style when using the component. DatePickerIOS does this by wrapping the native component in an extra view, which has flexible styling, and using a fixed style (which is generated with constants passed in from native) on the inner native component:
This guide covered many of the aspects of bridging over custom native components, but there is even more you might need to consider, such as custom hooks for inserting and laying out subviews. If you want to go even deeper, check out the actual RCTMapManager and other components in the source code.
Native Modules # | Edit on GitHub |
Sometimes an app needs access to a platform API that React Native doesn't have a corresponding module for yet. Maybe you want to reuse some existing Java code without having to reimplement it in JavaScript, or write some high performance, multi-threaded code such as for image processing, a database, or any number of advanced extensions.
We designed React Native such that it is possible for you to write real native code and have access to the full power of the platform. This is a more advanced feature and we don't expect it to be part of the usual development process, however it is essential that it exists. If React Native doesn't support a native feature that you need, you should be able to build it yourself.
This guide will use the Toast example. Let's say we would like to be able to create a toast message from JavaScript.
We start by creating a native module. A native module is a Java class that usually extends the ReactContextBaseJavaModule class and implements the functionality required by the JavaScript. Our goal here is to be able to write ToastAndroid.show('Awesome', ToastAndroid.SHORT); from JavaScript to display a short toast on the screen.
Native Modules # | Edit on GitHub |
Sometimes an app needs access to a platform API that React Native doesn't have a corresponding module for yet. Maybe you want to reuse some existing Java code without having to reimplement it in JavaScript, or write some high performance, multi-threaded code such as for image processing, a database, or any number of advanced extensions.
We designed React Native such that it is possible for you to write real native code and have access to the full power of the platform. This is a more advanced feature and we don't expect it to be part of the usual development process, however it is essential that it exists. If React Native doesn't support a native feature that you need, you should be able to build it yourself.
This guide will use the Toast example. Let's say we would like to be able to create a toast message from JavaScript.
We start by creating a native module. A native module is a Java class that usually extends the ReactContextBaseJavaModule class and implements the functionality required by the JavaScript. Our goal here is to be able to write ToastAndroid.show('Awesome', ToastAndroid.SHORT); from JavaScript to display a short toast on the screen.
To expose a method to JavaScript a Java method must be annotated using @ReactMethod. The return type of bridge methods is always void. React Native bridge is asynchronous, so the only way to pass a result to JavaScript is by using callbacks or emitting events (see below).
The following argument types are supported for methods annotated with @ReactMethod and they directly map to their JavaScript equivalents
The following argument types are supported for methods annotated with @ReactMethod and they directly map to their JavaScript equivalents
Read more about ReadableMap and ReadableArray
The last step within Java is to register the Module; this happens in the createNativeModules of your apps package. If a module is not registered it will not be available from JavaScript.
Read more about ReadableMap and ReadableArray
The last step within Java is to register the Module; this happens in the createNativeModules of your apps package. If a module is not registered it will not be available from JavaScript.
Now, from your other JavaScript file you can call the method like this:
Now, from your other JavaScript file you can call the method like this:
Native modules also support a special kind of argument - a callback. In most cases it is used to provide the function call result to JavaScript.
Native modules also support a special kind of argument - a callback. In most cases it is used to provide the function call result to JavaScript.
A native module is supposed to invoke its callback only once. It can, however, store the callback and invoke it later.
It is very important to highlight that the callback is not invoked immediately after the native function completes - remember that bridge communication is asynchronous, and this too is tied to the run loop.
Native modules can also fulfill a promise, which can simplify your code, especially when using ES2016's async/await syntax. When the last parameter of a bridged native method is a Promise, its corresponding JS method will return a JS Promise object.
Refactoring the above code to use a promise instead of callbacks looks like this:
A native module is supposed to invoke its callback only once. It can, however, store the callback and invoke it later.
It is very important to highlight that the callback is not invoked immediately after the native function completes - remember that bridge communication is asynchronous, and this too is tied to the run loop.
Native modules can also fulfill a promise, which can simplify your code, especially when using ES2016's async/await syntax. When the last parameter of a bridged native method is a Promise, its corresponding JS method will return a JS Promise object.
Refactoring the above code to use a promise instead of callbacks looks like this:
Native modules should not have any assumptions about what thread they are being called on, as the current assignment is subject to change in the future. If a blocking call is required, the heavy work should be dispatched to an internally managed worker thread, and any callbacks distributed from there.
Native modules can signal events to JavaScript without being invoked directly. The easiest way to do this is to use the RCTDeviceEventEmitter which can be obtained from the ReactContext as in the code snippet below.
Native modules should not have any assumptions about what thread they are being called on, as the current assignment is subject to change in the future. If a blocking call is required, the heavy work should be dispatched to an internally managed worker thread, and any callbacks distributed from there.
Native modules can signal events to JavaScript without being invoked directly. The easiest way to do this is to use the RCTDeviceEventEmitter which can be obtained from the ReactContext as in the code snippet below.
JavaScript modules can then register to receive events by addListenerOn using the Subscribable mixin
JavaScript modules can then register to receive events by addListenerOn using the Subscribable mixin
startActivityForResult #You'll need to listen to onActivityResult if you want to get results from an activity you started with startActivityForResult. To to do this, the module must implement ActivityEventListener. Then, you need to register a listener in the module's constructor,
Now you can listen to onActivityResult by implementing the following method:
startActivityForResult #You'll need to listen to onActivityResult if you want to get results from an activity you started with startActivityForResult. To to do this, the module must implement ActivityEventListener. Then, you need to register a listener in the module's constructor,
Now you can listen to onActivityResult by implementing the following method:
We will implement a simple image picker to demonstrate this. The image picker will expose the method pickImage to JavaScript, which will return the path of the image when called.
Listening to the activity's LifeCycle events such as onResume, onPause etc. is very similar to how we implemented ActivityEventListener. The module must implement ActivityEventListener. Then, you need to register a listener in the module's constructor,
Now you can listen to the activity's LifeCycle events by implementing the following methods:
Listening to the activity's LifeCycle events such as onResume, onPause etc. is very similar to how we implemented ActivityEventListener. The module must implement LifecycleEventListener. Then, you need to register a listener in the module's constructor,
Now you can listen to the activity's LifeCycle events by implementing the following methods:
Native Modules # | Edit on GitHub |
Sometimes an app needs access to platform API, and React Native doesn't have a corresponding module yet. Maybe you want to reuse some existing Objective-C, Swift or C++ code without having to reimplement it in JavaScript, or write some high performance, multi-threaded code such as for image processing, a database, or any number of advanced extensions.
We designed React Native such that it is possible for you to write real native code and have access to the full power of the platform. This is a more advanced feature and we don't expect it to be part of the usual development process, however it is essential that it exists. If React Native doesn't support a native feature that you need, you should be able to build it yourself.
This is a more advanced guide that shows how to build a native module. It assumes the reader knows Objective-C or Swift and core libraries (Foundation, UIKit).
This guide will use the iOS Calendar API example. Let's say we would like to be able to access the iOS calendar from JavaScript.
A native module is just an Objective-C class that implements the RCTBridgeModule protocol. If you are wondering, RCT is an abbreviation of ReaCT.
Native Modules # | Edit on GitHub |
Sometimes an app needs access to platform API, and React Native doesn't have a corresponding module yet. Maybe you want to reuse some existing Objective-C, Swift or C++ code without having to reimplement it in JavaScript, or write some high performance, multi-threaded code such as for image processing, a database, or any number of advanced extensions.
We designed React Native such that it is possible for you to write real native code and have access to the full power of the platform. This is a more advanced feature and we don't expect it to be part of the usual development process, however it is essential that it exists. If React Native doesn't support a native feature that you need, you should be able to build it yourself.
This is a more advanced guide that shows how to build a native module. It assumes the reader knows Objective-C or Swift and core libraries (Foundation, UIKit).
This guide will use the iOS Calendar API example. Let's say we would like to be able to access the iOS calendar from JavaScript.
A native module is just an Objective-C class that implements the RCTBridgeModule protocol. If you are wondering, RCT is an abbreviation of ReaCT.
React Native will not expose any methods of CalendarManager to JavaScript unless explicitly told to. This is done using the RCT_EXPORT_METHOD() macro:
Now, from your JavaScript file you can call the method like this:
NOTE: JavaScript method names
The name of the method exported to JavaScript is the native method's name up to the first colon. React Native also defines a macro called
RCT_REMAP_METHOD()to specify the JavaScript method's name. This is useful when multiple native methods are the same up to the first colon and would have conflicting JavaScript names.
The return type of bridge methods is always void. React Native bridge is asynchronous, so the only way to pass a result to JavaScript is by using callbacks or emitting events (see below).
RCT_EXPORT_METHOD supports all standard JSON object types, such as:
NSString)NSInteger, float, double, CGFloat, NSNumber)BOOL, NSNumber)NSArray) of any types from this listNSDictionary) with string keys and values of any type from this listRCTResponseSenderBlock)But it also works with any type that is supported by the RCTConvert class (see RCTConvert for details). The RCTConvert helper functions all accept a JSON value as input and map it to a native Objective-C type or class.
In our CalendarManager example, we need to pass the event date to the native method. We can't send JavaScript Date objects over the bridge, so we need to convert the date to a string or number. We could write our native function like this:
Now, from your JavaScript file you can call the method like this:
NOTE: JavaScript method names
The name of the method exported to JavaScript is the native method's name up to the first colon. React Native also defines a macro called
RCT_REMAP_METHOD()to specify the JavaScript method's name. This is useful when multiple native methods are the same up to the first colon and would have conflicting JavaScript names.
The return type of bridge methods is always void. React Native bridge is asynchronous, so the only way to pass a result to JavaScript is by using callbacks or emitting events (see below).
RCT_EXPORT_METHOD supports all standard JSON object types, such as:
NSString)NSInteger, float, double, CGFloat, NSNumber)BOOL, NSNumber)NSArray) of any types from this listNSDictionary) with string keys and values of any type from this listRCTResponseSenderBlock)But it also works with any type that is supported by the RCTConvert class (see RCTConvert for details). The RCTConvert helper functions all accept a JSON value as input and map it to a native Objective-C type or class.
In our CalendarManager example, we need to pass the event date to the native method. We can't send JavaScript Date objects over the bridge, so we need to convert the date to a string or number. We could write our native function like this:
or like this:
NOTE: About array and map
Objective-C doesn't provide any guarantees about the types of values in these structures. Your native module might expect an array of strings, but if JavaScript calls your method with an array containing numbers and strings, you'll get an
NSArraycontaining a mix ofNSNumberandNSString. For arrays,RCTConvertprovides some typed collections you can use in your method declaration, such asNSStringArray, orUIColorArray. For maps, it is the developer's responsibility to check the value types individually by manually callingRCTConverthelper methods.
WARNING
This section is more experimental than others because we don't have a solid set of best practices around callbacks yet.
Native modules also supports a special kind of argument- a callback. In most cases it is used to provide the function call result to JavaScript.
NOTE: About array and map
Objective-C doesn't provide any guarantees about the types of values in these structures. Your native module might expect an array of strings, but if JavaScript calls your method with an array containing numbers and strings, you'll get an
NSArraycontaining a mix ofNSNumberandNSString. For arrays,RCTConvertprovides some typed collections you can use in your method declaration, such asNSStringArray, orUIColorArray. For maps, it is the developer's responsibility to check the value types individually by manually callingRCTConverthelper methods.
WARNING
This section is more experimental than others because we don't have a solid set of best practices around callbacks yet.
Native modules also supports a special kind of argument- a callback. In most cases it is used to provide the function call result to JavaScript.
A native module is supposed to invoke its callback only once. It can, however, store the callback and invoke it later. This pattern is often used to wrap iOS APIs that require delegates. See RCTAlertManager for an example.
If you want to pass error-like objects to JavaScript, use RCTMakeError from RCTUtils.h. Right now this just passes an Error-shaped dictionary to JavaScript, but we would like to automatically generate real JavaScript Error objects in the future.
Native modules can also fulfill a promise, which can simplify your code, especially when using ES2016's async/await syntax. When the last parameters of a bridged native method are an RCTPromiseResolveBlock and RCTPromiseRejectBlock, its corresponding JS method will return a JS Promise object.
Refactoring the above code to use a promise instead of callbacks looks like this:
A native module is supposed to invoke its callback only once. It can, however, store the callback and invoke it later. This pattern is often used to wrap iOS APIs that require delegates. See RCTAlertManager for an example.
If you want to pass error-like objects to JavaScript, use RCTMakeError from RCTUtils.h. Right now this just passes an Error-shaped dictionary to JavaScript, but we would like to automatically generate real JavaScript Error objects in the future.
Native modules can also fulfill a promise, which can simplify your code, especially when using ES2016's async/await syntax. When the last parameters of a bridged native method are an RCTPromiseResolveBlock and RCTPromiseRejectBlock, its corresponding JS method will return a JS Promise object.
Refactoring the above code to use a promise instead of callbacks looks like this:
The JavaScript counterpart of this method returns a Promise. This means you can use the await keyword within an async function to call it and wait for its result:
The native module should not have any assumptions about what thread it is being called on. React Native invokes native modules methods on a separate serial GCD queue, but this is an implementation detail and might change. The - (dispatch_queue_t)methodQueue method allows the native module to specify which queue its methods should be run on. For example, if it needs to use a main-thread-only iOS API, it should specify this via:
The native module should not have any assumptions about what thread it is being called on. React Native invokes native modules methods on a separate serial GCD queue, but this is an implementation detail and might change. The - (dispatch_queue_t)methodQueue method allows the native module to specify which queue its methods should be run on. For example, if it needs to use a main-thread-only iOS API, it should specify this via:
Similarly, if an operation may take a long time to complete, the native module should not block and can specify it's own queue to run operations on. For example, the RCTAsyncLocalStorage module creates it's own queue so the React queue isn't blocked waiting on potentially slow disk access:
NOTE: Sharing dispatch queues between modules
The
methodQueuemethod will be called once when the module is initialized, and then retained by the bridge, so there is no need to retain the queue yourself, unless you wish to make use of it within your module. However, if you wish to share the same queue between multiple modules then you will need to ensure that you retain and return the same queue instance for each of them; merely returning a queue of the same name for each won't work.
A native module can export constants that are immediately available to JavaScript at runtime. This is useful for communicating static data that would otherwise require a round-trip through the bridge.
NOTE: Sharing dispatch queues between modules
The
methodQueuemethod will be called once when the module is initialized, and then retained by the bridge, so there is no need to retain the queue yourself, unless you wish to make use of it within your module. However, if you wish to share the same queue between multiple modules then you will need to ensure that you retain and return the same queue instance for each of them; merely returning a queue of the same name for each won't work.
A native module can export constants that are immediately available to JavaScript at runtime. This is useful for communicating static data that would otherwise require a round-trip through the bridge.
JavaScript can use this value right away, synchronously:
Note that the constants are exported only at initialization time, so if you change constantsToExport values at runtime it won't affect the JavaScript environment.
Enums that are defined via NS_ENUM cannot be used as method arguments without first extending RCTConvert.
In order to export the following NS_ENUM definition:
JavaScript can use this value right away, synchronously:
Note that the constants are exported only at initialization time, so if you change constantsToExport values at runtime it won't affect the JavaScript environment.
Enums that are defined via NS_ENUM cannot be used as method arguments without first extending RCTConvert.
In order to export the following NS_ENUM definition:
Your enum will then be automatically unwrapped using the selector provided (integerValue in the above example) before being passed to your exported method.
The native module can signal events to JavaScript without being invoked directly. The easiest way to do this is to use eventDispatcher:
Your enum will then be automatically unwrapped using the selector provided (integerValue in the above example) before being passed to your exported method.
The native module can signal events to JavaScript without being invoked directly. The easiest way to do this is to use eventDispatcher:
JavaScript code can subscribe to these events:
JavaScript code can subscribe to these events:
For more examples of sending events to JavaScript, see RCTLocationObserver.
Swift doesn't have support for macros so exposing it to React Native requires a bit more setup but works relatively the same.
Let's say we have the same CalendarManager but as a Swift class:
For more examples of sending events to JavaScript, see RCTLocationObserver.
Swift doesn't have support for macros so exposing it to React Native requires a bit more setup but works relatively the same.
Let's say we have the same CalendarManager but as a Swift class:
For those of you new to Swift and Objective-C, whenever you mix the two languages in an iOS project, you will also need an additional bridging file, known as a bridging header, to expose the Objective-C files to Swift. Xcode will offer to create this header file for you if you add your Swift file to your app through the Xcode File>New File menu option. You will need to import RCTBridgeModule.h in this header file.
You can also use RCT_EXTERN_REMAP_MODULE and RCT_EXTERN_REMAP_METHOD to alter the JavaScript name of the module or methods you are exporting. For more information see RCTBridgeModule.
NativeMethodsMixin # | Edit on GitHub |
NativeMethodsMixin provides methods to access the underlying native
+
NativeMethodsMixin # | Edit on GitHub |
NativeMethodsMixin provides methods to access the underlying native
component directly. This can be useful in cases when you want to focus
a view or measure its on-screen dimensions, for example.
The methods described here are available on most of the default components provided by React Native. Note, however, that they are not available on composite components that aren't directly backed by a native view. This will generally include most components that you define in your own app. For more information, see Direct -Manipulation.
Determines the location on screen, width, and height of the given view and +Manipulation.
Determines the location on screen, width, and height of the given view and returns the values via an async callback. If successful, the callback will be called with the following arguments:
Note that these measurements are not available until after the rendering
has been completed in native. If you need the measurements as soon as
possible, consider using the onLayout
-prop instead.
Like measure(), but measures the view relative an ancestor,
+prop instead.
Like measure(), but measures the view relative an ancestor,
specified as relativeToNativeNode. This means that the returned x, y
are relative to the origin x, y of the ancestor view.
As always, to obtain a native node handle for a component, you can use
-React.findNodeHandle(component).
This function sends props straight to native. They will not participate in
+React.findNodeHandle(component).
This function sends props straight to native. They will not participate in future diff process - this means that if you do not include them in the next render, they will remain active (see Direct -Manipulation).
Requests focus for the given input or view. The exact behavior triggered -will depend on the platform and type of view.
Removes focus from an input or view. This is the opposite of focus().
Navigator Comparison # | Edit on GitHub |
The differences between Navigator +
Navigator Comparison # | Edit on GitHub |
The differences between Navigator and NavigatorIOS are a common source of confusion for newcomers.
Both Navigator and NavigatorIOS are components that allow you to
manage the navigation in your app between various "scenes" (another word
@@ -12,7 +12,7 @@ class, and Navigator re-implements that functionality entirely in
JavaScript as a React component. A corollary of this is that Navigator
will be compatible with Android and iOS, whereas NavigatorIOS will
only work on the one platform. Below is an itemized list of differences
-between the two.
NavigatorIOS bar: Navigator.NavigationBar, and another with breadcrumbs called Navigator.BreadcrumbNavigationBar. See the UIExplorer demo to try them out and see how to use them.NavigatorIOS.navigationBar prop.Navigator in its current form.For most non-trivial apps, you will want to use Navigator - it won't be long before you run into issues when trying to do anything complex with NavigatorIOS.
Navigator # | Edit on GitHub |
Use Navigator to transition between different scenes in your app. To
+
Navigator # | Edit on GitHub |
Use Navigator to transition between different scenes in your app. To
accomplish this, provide route objects to the navigator to identify each
scene, and also a renderScene function that the navigator can use to
render the scene for a given route.
To change the animation or gesture properties of the scene, provide a
configureScene prop to get the config object for a given route. See
Navigator.SceneConfigs for default animations and more info on
-scene config options.
If you have a ref to the Navigator element, you can invoke several methods + />
If you have a ref to the Navigator element, you can invoke several methods on it to trigger navigation:
getCurrentRoutes() - returns the current list of routesjumpBack() - Jump backward without unmounting the current scenejumpForward() - Jump forward to the next scene in the route stackjumpTo(route) - Transition to an existing scene without unmountingpush(route) - Navigate forward to a new scene, squashing any scenes
that you could jumpForward topop() - Transition back and unmount the current scenereplace(route) - Replace the current scene with a new routereplaceAtIndex(route, index) - Replace a scene as specified by an indexreplacePrevious(route) - Replace the previous sceneresetTo(route) - Navigate to a new scene and reset route stackimmediatelyResetRouteStack(routeStack) - Reset every scene with an
array of routespopToRoute(route) - Pop to a particular scene, as specified by its
route. All scenes after it will be unmountedpopToTop() - Pop to the first scene in the stack, unmounting every
- other sceneOptional function that allows configuration about scene animations and + other scene
Optional function that allows configuration about scene animations and gestures. Will be invoked with the route and the routeStack and should -return a scene configuration object
Specify a route to start on. A route is an object that the navigator +return a scene configuration object
Specify a route to start on. A route is an object that the navigator
will use to identify each scene to render. initialRoute must be
a route in the initialRouteStack if both props are provided. The
-initialRoute will default to the last item in the initialRouteStack.
Provide a set of routes to initially mount. Required if no initialRoute
+initialRoute will default to the last item in the initialRouteStack.
Provide a set of routes to initially mount. Required if no initialRoute
is provided. Otherwise, it will default to an array containing only the
-initialRoute
Optionally provide a navigation bar that persists across scene -transitions
Optionally provide the navigator object from a parent Navigator
DeprecatedUse navigationContext.addListener('didfocus', callback) instead.
Will be called with the new route of each scene after the transition is -complete or after the initial mounting
DeprecatedUse navigationContext.addListener('willfocus', callback) instead.
Will emit the target route upon mounting and before each nav transition
Required function which renders the scene for a given route. Will be
+initialRoute
Optionally provide a navigation bar that persists across scene +transitions
Optionally provide the navigator object from a parent Navigator
Will be called with the new route of each scene after the transition is +complete or after the initial mounting
Will emit the target route upon mounting and before each nav transition
Required function which renders the scene for a given route. Will be invoked with the route and the navigator object
Styles to apply to the container of each scene
NavigatorIOS # | Edit on GitHub |
NavigatorIOS wraps UIKit navigation and allows you to add back-swipe +
NavigatorIOS # | Edit on GitHub |
NavigatorIOS wraps UIKit navigation and allows you to add back-swipe functionality across your app.
NOTE: This Component is not maintained by Facebook
This component is under community responsibility. If a pure JavaScript solution fits your needs you may try the
Navigator-component instead.
A route is an object used to describe each page in the navigator. The first +component instead.
A route is an object used to describe each page in the navigator. The first
route is provided to NavigatorIOS as initialRoute:
initialRoute:Now MyView will be rendered by the navigator. It will receive the route
object in the route prop, a navigator, and all of the props specified in
-passProps.
See the initialRoute propType for a complete definition of a route.
A navigator is an object of navigation functions that a view can call. It
+passProps.
See the initialRoute propType for a complete definition of a route.
A navigator is an object of navigation functions that a view can call. It
is passed as a prop to any component rendered by NavigatorIOS.
resetTo(route) - Replaces the top it
});Props passed to the NavigatorIOS component will set the default configuration for the navigation bar. Props passed as properties to a route object will set the configuration for that route's navigation bar, overriding any props -passed to the NavigatorIOS component.
The default background color of the navigation bar
NavigatorIOS uses "route" objects to identify child views, their props, +passed to the NavigatorIOS component.
The default background color of the navigation bar
NavigatorIOS uses "route" objects to identify child views, their props, and navigation bar configuration. "push" and all the other navigation -operations expect routes to be like this:
The default wrapper style for components in the navigator. -A common use case is to set the backgroundColor for every page
A Boolean value that indicates whether the navigation bar is hidden by default
A Boolean value that indicates whether to hide the 1px hairline shadow by default
The default color used for buttons in the navigation bar
The default text color of the navigation bar title
A Boolean value that indicates whether the navigation bar is translucent by default
Examples # | Edit on GitHub |
The default wrapper style for components in the navigator. +A common use case is to set the backgroundColor for every page
A Boolean value that indicates whether the navigation bar is hidden by default
A Boolean value that indicates whether to hide the 1px hairline shadow by default
The default color used for buttons in the navigation bar
The default text color of the navigation bar title
A Boolean value that indicates whether the navigation bar is translucent by default
Examples # | Edit on GitHub |
NetInfo # | Edit on GitHub |
NetInfo exposes info about online/offline status
NetInfo # | Edit on GitHub |
NetInfo exposes info about online/offline status
Asynchronously determine if the device is online and on a cellular network.
none - device is offlinewifi - device is online and connected via wifi, or is the iOS simulatorcell - device is connected via Edge, 3G, WiMax, or LTEunknown - error case and the network status is unknownTo request network info, you need to add the following line to your +);
Asynchronously determine if the device is online and on a cellular network.
none - device is offlinewifi - device is online and connected via wifi, or is the iOS simulatorcell - device is connected via Edge, 3G, WiMax, or LTEunknown - error case and the network status is unknownTo request network info, you need to add the following line to your
app's AndroidManifest.xml:
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
-Asynchronously determine if the device is connected and details about that connection.
Android Connectivity Types.
NONE - device is offlineBLUETOOTH - The Bluetooth data connection.DUMMY - Dummy data connection.ETHERNET - The Ethernet data connection.MOBILE - The Mobile data connection.MOBILE_DUN - A DUN-specific Mobile data connection.MOBILE_HIPRI - A High Priority Mobile data connection.MOBILE_MMS - An MMS-specific Mobile data connection.MOBILE_SUPL - A SUPL-specific Mobile data connection.VPN - A virtual network using one or more native bearers. Requires API Level 21WIFI - The WIFI data connection.WIMAX - The WiMAX data connection.UNKNOWN - Unknown data connection.The rest ConnectivityStates are hidden by the Android API, but can be used if necessary.
Available on Android. Detect if the current active connection is metered or not. A network is +Asynchronously determine if the device is connected and details about that connection.
Android Connectivity Types.
NONE - device is offlineBLUETOOTH - The Bluetooth data connection.DUMMY - Dummy data connection.ETHERNET - The Ethernet data connection.MOBILE - The Mobile data connection.MOBILE_DUN - A DUN-specific Mobile data connection.MOBILE_HIPRI - A High Priority Mobile data connection.MOBILE_MMS - An MMS-specific Mobile data connection.MOBILE_SUPL - A SUPL-specific Mobile data connection.VPN - A virtual network using one or more native bearers. Requires API Level 21WIFI - The WIFI data connection.WIMAX - The WiMAX data connection.UNKNOWN - Unknown data connection.The rest ConnectivityStates are hidden by the Android API, but can be used if necessary.
Available on Android. Detect if the current active connection is metered or not. A network is classified as metered when the user is sensitive to heavy data usage on that connection due to monetary costs, data limitations or battery/performance issues.
Available on all platforms. Asynchronously fetch a boolean to determine +});
Available on all platforms. Asynchronously fetch a boolean to determine internet connectivity.
Examples # | Edit on GitHub |
Examples # | Edit on GitHub |
Network # | Edit on GitHub |
One of React Native's goals is to be a playground where we can experiment with different architectures and crazy ideas. Since browsers are not flexible enough, we had no choice but to reimplement the entire stack. In the places that we did not intend to change anything, we tried to be as faithful as possible to the browser APIs. The networking stack is a great example.
fetch is a better networking API being worked on by the standards committee and is already available in Chrome. It is available in React Native by default.
Include a request object as the optional second argument to customize the HTTP request:
Network # | Edit on GitHub |
One of React Native's goals is to be a playground where we can experiment with different architectures and crazy ideas. Since browsers are not flexible enough, we had no choice but to reimplement the entire stack. In the places that we did not intend to change anything, we tried to be as faithful as possible to the browser APIs. The networking stack is a great example.
fetch is a better networking API being worked on by the standards committee and is already available in Chrome. It is available in React Native by default.
Include a request object as the optional second argument to customize the HTTP request:
fetch returns a Promise that can be processed in two ways:
then and catch in synchronous code:async/await syntax:fetch returns a Promise that can be processed in two ways:
Using then and catch in synchronous code:
Called within an asynchronous function using ES7 async/await syntax:
WebSocket is a protocol providing full-duplex communication channels over a single TCP connection.
Note: Errors thrown by rejected Promises need to be caught, or they will be swallowed silently
WebSocket is a protocol providing full-duplex communication channels over a single TCP connection.
XMLHttpRequest API is implemented on-top of iOS networking apis. The notable difference from web is the security model: you can read from arbitrary websites on the internet since there is no concept of CORS.
XMLHttpRequest API is implemented on-top of iOS networking apis. The notable difference from web is the security model: you can read from arbitrary websites on the internet since there is no concept of CORS.
Please follow the MDN Documentation for a complete description of the API.
As a developer, you're probably not going to use XMLHttpRequest directly as its API is very tedious to work with. But the fact that it is implemented and compatible with the browser API gives you the ability to use third-party libraries such as Parse, frisbee, or axios directly from npm.
PanResponder # | Edit on GitHub |
PanResponder reconciles several touches into a single gesture. It makes
+
PanResponder # | Edit on GitHub |
PanResponder reconciles several touches into a single gesture. It makes
single-touch gestures resilient to extra touches, and can be used to
recognize simple multi-touch gestures.
It provides a predictable wrapper of the responder handlers provided by the
gesture responder system.
For each handler, it provides a new gestureState object alongside the
native event object:
A native event is a synthetic touch event with the following form:
nativeEventchangedTouches - Array of all touch events that have changed since the last eventidentifier - The ID of the touchlocationX - The X position of the touch, relative to the elementlocationY - The Y position of the touch, relative to the elementpageX - The X position of the touch, relative to the root elementpageY - The Y position of the touch, relative to the root elementtarget - The node id of the element receiving the touch eventtimestamp - A time identifier for the touch, useful for velocity calculationtouches - Array of all current touches on the screenA gestureState object has the following:
stateID - ID of the gestureState- persisted as long as there at least
- one touch on screenmoveX - the latest screen coordinates of the recently-moved touchmoveY - the latest screen coordinates of the recently-moved touchx0 - the screen coordinates of the responder granty0 - the screen coordinates of the responder grantdx - accumulated distance of the gesture since the touch starteddy - accumulated distance of the gesture since the touch startedvx - current velocity of the gesturevy - current velocity of the gesturenumberActiveTouches - Number of touches currently on screenmoveX - the latest screen coordinates of the recently-moved touchmoveY - the latest screen coordinates of the recently-moved touchx0 - the screen coordinates of the responder granty0 - the screen coordinates of the responder grantdx - accumulated distance of the gesture since the touch starteddy - accumulated distance of the gesture since the touch startedvx - current velocity of the gesturevy - current velocity of the gesturenumberActiveTouches - Number of touches currently on screenTo see it in action, try the -PanResponder example in UIExplorer
@param {object} config Enhanced versions of all of the responder callbacks +