diff --git a/releases/next/css/react-native.css b/releases/next/css/react-native.css index 7d506e34ec2..d51ddd575df 100644 --- a/releases/next/css/react-native.css +++ b/releases/next/css/react-native.css @@ -1373,45 +1373,12 @@ div[data-twttr-id] iframe { background-color: hsl(198, 100%, 94%); } -.survey { - padding: 10px; - padding-top: 0; - background-color: rgba(5, 165, 209, 0.05); - border: 2px solid #05A5D1; - position: relative; -} - -.survey-image { - float: left; - height: 128px; - width: 128px; - background-image: url('../img/survey.png'); -} - -.survey p { - margin-left: 130px; -} - -.survey .button { - font-size: 24px; - background: #05A5D1; - color: #fafafa; -} - @media only screen and (max-device-width: 1024px) { #content { display: inline; } - .survey-image { - position: static; - margin: 10px auto; - } - .survey p { - margin-left: 0px; - } - .container { min-width: 0; overflow: auto; diff --git a/releases/next/docs/accessibility.html b/releases/next/docs/accessibility.html index a26998381dd..f3698db78e6 100644 --- a/releases/next/docs/accessibility.html +++ b/releases/next/docs/accessibility.html @@ -38,7 +38,7 @@ <CustomRadioButton accessibleComponentType={this.state.radioButton} - onPress={this._onPress}/>
In the above example we've created a custom radio button that now behaves like a native one. More specifically, TalkBack now correctly announces changes to the radio button selection.
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.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
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.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
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.
Components # | Edit on GitHub |
Components are the building blocks for a React Native application. A React Native user interface (UI) is specified by declaring components, possibly nested, and then those components are mapped to the native UI on the targeted platform.
React Native has a number of core components that are commonly used in applications, either on their own or combined to build new components.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
Components # | Edit on GitHub |
Components are the building blocks for a React Native application. A React Native user interface (UI) is specified by declaring components, possibly nested, and then those components are mapped to the native UI on the targeted platform.
React Native has a number of core components that are commonly used in applications, either on their own or combined to build new components.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
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:
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
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:
Debugging # | Edit on GitHub |
You can access the developer menu by shaking your device or by selecting "Shake Gesture" inside the Hardware menu in the iOS Simulator. You can also use the Command⌘ + D keyboard shortcut when your app is running in the iPhone Simulator, or Command⌘ + M when running in an Android emulator.

The Developer Menu is disabled in release (production) builds.
Selecting Reload from the Developer Menu will reload the JavaScript that powers your application. You can also press Command⌘ + R in the iOS Simulator, or press R twice on Android emulators.
If you are using a Dvorak/Colemak layout, use the
Command⌘ + Pkeyboard shortcut to reload the simulator.
You will need to rebuild your app for changes to take effect in certain situations:
Images.xcassets on iOS or in res/drawable folder on Android.If the
Command⌘ + Rkeyboard shortcut does not seem to reload the iOS Simulator, go to the Hardware menu, select Keyboard, and make sure that "Connect Hardware Keyboard" is checked.
You may enable Live Reload to automatically trigger a reload whenever your JavaScript code changes.
Live Reload is available on iOS via the Developer Menu. On Android, select "Dev Settings" from the Developer Menu and enable "Auto reload on JS change".
Errors and warnings are displayed inside your app in development builds.
In-app errors are displayed in a full screen alert with a red background inside your app. This screen is known as a RedBox. You can use console.error() to manually trigger one.
Warnings will be displayed on screen with a yellow background. These alerts are known as YellowBoxes. Click on the alerts to show more information or to dismiss them.
As with a RedBox, you can use console.warn() to trigger a YellowBox.
YellowBoxes can be disabled during development by using console.disableYellowBox = true;. Specific warnings can be ignored programmatically by setting an array of prefixes that should be ignored: console.ignoredYellowBox = ['Warning: ...'];
RedBoxes and YellowBoxes are automatically disabled in release (production) builds.
To view detailed logs on iOS, open your app in Xcode, then Build and Run your app on a device or the iPhone Simulator. The console should appear automatically after the app launches. If your app is failing to build, check the Issues Navigator in Xcode.
Run adb logcat *:S ReactNative:V ReactNativeJS:V in a terminal to display the logs for an Android app running on a device or an emulator.
To debug the JavaScript code in Chrome, select Debug JS Remotely from the Developer Menu. This will open a new tab at http://localhost:8081/debugger-ui.
In Chrome, press Command⌘ + Option⌥ + I or select View → Developer → Developer Tools to toggle the developer tools console. Enable Pause On Caught Exceptions for a better debugging experience.
On iOS devices, open the file RCTWebSocketExecutor.m and change localhost to the IP address of your computer, then select Debug JS Remotely from the Developer Menu.
On Android 5.0+ devices connected via USB, you can use the adb command line tool to setup port forwarding from the device to your computer:
adb reverse tcp:8081 tcp:8081
Alternatively, select Dev Settings from the Developer Menu, then update the Debug server host for device setting to match the IP address of your computer.
If you run into any issues, it may be possible that one of your Chrome extensions is interacting in unexpected ways with the debugger. Try disabling all of your extensions and re-enabling them one-by-one until you find the problematic extension.
To use a custom JavaScript debugger in place of Chrome Developer Tools, set the REACT_DEBUGGER environment variable to a command that will start your custom debugger. You can then select Debug JS Remotely from the Developer Menu to start debugging.
The debugger will receive a list of all project roots, separated by a space. For example, if you set
REACT_DEBUGGER="node /path/to/launchDebugger.js --port 2345 --type ReactNative", then the commandnode /path/to/launchDebugger.js --port 2345 --type ReactNative /path/to/reactNative/appwill be used to start your debugger. Custom debugger commands executed this way should be short-lived processes, and they shouldn't produce more than 200 kilobytes of output.
You can enable a FPS graph overlay in the Developer Menu in order to help you debug performance problems.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
Debugging # | Edit on GitHub |
You can access the developer menu by shaking your device or by selecting "Shake Gesture" inside the Hardware menu in the iOS Simulator. You can also use the Command⌘ + D keyboard shortcut when your app is running in the iPhone Simulator, or Command⌘ + M when running in an Android emulator.

The Developer Menu is disabled in release (production) builds.
Selecting Reload from the Developer Menu will reload the JavaScript that powers your application. You can also press Command⌘ + R in the iOS Simulator, or press R twice on Android emulators.
If you are using a Dvorak/Colemak layout, use the
Command⌘ + Pkeyboard shortcut to reload the simulator.
You will need to rebuild your app for changes to take effect in certain situations:
Images.xcassets on iOS or in res/drawable folder on Android.If the
Command⌘ + Rkeyboard shortcut does not seem to reload the iOS Simulator, go to the Hardware menu, select Keyboard, and make sure that "Connect Hardware Keyboard" is checked.
You may enable Live Reload to automatically trigger a reload whenever your JavaScript code changes.
Live Reload is available on iOS via the Developer Menu. On Android, select "Dev Settings" from the Developer Menu and enable "Auto reload on JS change".
Errors and warnings are displayed inside your app in development builds.
In-app errors are displayed in a full screen alert with a red background inside your app. This screen is known as a RedBox. You can use console.error() to manually trigger one.
Warnings will be displayed on screen with a yellow background. These alerts are known as YellowBoxes. Click on the alerts to show more information or to dismiss them.
As with a RedBox, you can use console.warn() to trigger a YellowBox.
YellowBoxes can be disabled during development by using console.disableYellowBox = true;. Specific warnings can be ignored programmatically by setting an array of prefixes that should be ignored: console.ignoredYellowBox = ['Warning: ...'];
RedBoxes and YellowBoxes are automatically disabled in release (production) builds.
To view detailed logs on iOS, open your app in Xcode, then Build and Run your app on a device or the iPhone Simulator. The console should appear automatically after the app launches. If your app is failing to build, check the Issues Navigator in Xcode.
Run adb logcat *:S ReactNative:V ReactNativeJS:V in a terminal to display the logs for an Android app running on a device or an emulator.
To debug the JavaScript code in Chrome, select Debug JS Remotely from the Developer Menu. This will open a new tab at http://localhost:8081/debugger-ui.
In Chrome, press Command⌘ + Option⌥ + I or select View → Developer → Developer Tools to toggle the developer tools console. Enable Pause On Caught Exceptions for a better debugging experience.
On iOS devices, open the file RCTWebSocketExecutor.m and change localhost to the IP address of your computer, then select Debug JS Remotely from the Developer Menu.
On Android 5.0+ devices connected via USB, you can use the adb command line tool to setup port forwarding from the device to your computer:
adb reverse tcp:8081 tcp:8081
Alternatively, select Dev Settings from the Developer Menu, then update the Debug server host for device setting to match the IP address of your computer.
If you run into any issues, it may be possible that one of your Chrome extensions is interacting in unexpected ways with the debugger. Try disabling all of your extensions and re-enabling them one-by-one until you find the problematic extension.
To use a custom JavaScript debugger in place of Chrome Developer Tools, set the REACT_DEBUGGER environment variable to a command that will start your custom debugger. You can then select Debug JS Remotely from the Developer Menu to start debugging.
The debugger will receive a list of all project roots, separated by a space. For example, if you set
REACT_DEBUGGER="node /path/to/launchDebugger.js --port 2345 --type ReactNative", then the commandnode /path/to/launchDebugger.js --port 2345 --type ReactNative /path/to/reactNative/appwill be used to start your debugger. Custom debugger commands executed this way should be short-lived processes, and they shouldn't produce more than 200 kilobytes of output.
You can enable a FPS graph overlay in the Developer Menu in order to help you debug performance problems.
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.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
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.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
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';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__We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
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';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>.
The work on React Native for Android started later than React Native for iOS. Most views and modules are now available on Android, with the following exceptions:
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>.ProgressBar could render a horizontal progress bar on both platforms (on iOS this is ProgressViewIOS, on Android it's ProgressBarAndroid).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.
Moving a React Native project after it has been compiled in iOS can sometimes cause errors with pre-compiled headers e.g. mv MyAwesomeProject/ newDir/MyAwesomeProject. This results in a message resembling: error: PCH was compiled with module cache path .... If you were compiling using Xcode you can hold option when you clean the build. If you're using react-native run-ios you can manually clean the header cache by deleting the contents of your ModuleCache folder. e.g. rm -rf ios/build/ModuleCache/*
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 underlineColorAndroid to transparent.
As of iOS 9, new Xcode projects enable App Transport Security by default, which rejects all HTTP requests that are not sent over HTTPS. This can result in HTTP traffic being blocked (including the developer React Native server) with the following console errors:
See our guide for running on an iOS device and working around the ATS issues, or several community posts on handling common cases like whitelisting specific domains for non-HTTPS traffic.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
Running On Device # | Edit on GitHub |
Note that running on device requires Apple Developer account and provisioning your iPhone. This guide covers only React Native specific topic.
You can iterate quickly on device using development server. Ensure that you are on the same WiFi network as your computer.
AwesomeApp/ios/AwesomeApp/AppDelegate.mlocalhost to your laptop's IP. On Mac, you can find the IP address in System Preferences / Network.NSAllowsArbitraryLoads entry to your Info.plist file. Since ATS does not allow insecure HTTP requests to IP addresses, you must completely disable it to run on a device. This is only a requirement for development on a device, and unless you can't workaround an issue you should leave ATS enabled for production builds. For more information, see this post on configuring ATS.Hint
Shake the device to open development menu (reload, debug, etc.)
When you run your app on device, we pack all the JavaScript code and the images used into the app's resources. This way you can test it without development server running and submit the app to the AppStore.
AwesomeApp/ios/AwesomeApp/AppDelegate.mjsCodeLocation = [[NSBundle mainBundle] ...Product > Scheme > Edit Scheme... in xcode and change Build Configuration between Debug and Release.When building your app for production, your app's scheme should be set to Release as detailed in the debugging documentation in order to disable the in-app developer menu.
If curl command fails make sure the packager is running. Also try adding --ipv4 flag to the end of it.
Note that since v0.14 JS and images are automatically packaged into the iOS app using Bundle React Native code and images Xcode build phase.
We are planning improvements to the React Native documentation. Your responses to this short survey will go a long way in helping us provide valuable content. Thank you!
Running On Device # | Edit on GitHub |
Note that running on device requires Apple Developer account and provisioning your iPhone. This guide covers only React Native specific topic.
You can iterate quickly on device using development server. Ensure that you are on the same WiFi network as your computer.
AwesomeApp/ios/AwesomeApp/AppDelegate.mlocalhost to your laptop's IP. On Mac, you can find the IP address in System Preferences / Network.NSAllowsArbitraryLoads entry to your Info.plist file. Since ATS does not allow insecure HTTP requests to IP addresses, you must completely disable it to run on a device. This is only a requirement for development on a device, and unless you can't workaround an issue you should leave ATS enabled for production builds. For more information, see this post on configuring ATS.Hint
Shake the device to open development menu (reload, debug, etc.)
When you run your app on device, we pack all the JavaScript code and the images used into the app's resources. This way you can test it without development server running and submit the app to the AppStore.
AwesomeApp/ios/AwesomeApp/AppDelegate.mjsCodeLocation = [[NSBundle mainBundle] ...Product > Scheme > Edit Scheme... in xcode and change Build Configuration between Debug and Release.When building your app for production, your app's scheme should be set to Release as detailed in the debugging documentation in order to disable the in-app developer menu.
If curl command fails make sure the packager is running. Also try adding --ipv4 flag to the end of it.
Note that since v0.14 JS and images are automatically packaged into the iOS app using Bundle React Native code and images Xcode build phase.