diff --git a/website/versioned_docs/version-0.5/accessibility.md b/website/versioned_docs/version-0.5/accessibility.md index c90414f01d2..e3b4bdf6ec2 100644 --- a/website/versioned_docs/version-0.5/accessibility.md +++ b/website/versioned_docs/version-0.5/accessibility.md @@ -8,7 +8,7 @@ original_id: accessibility Both iOS and Android provide APIs for making apps accessible to people with disabilities. In addition, both platforms provide bundled assistive technologies, like the screen readers VoiceOver (iOS) and TalkBack (Android) for the visually impaired. Similarly, in React Native we have included APIs designed to provide developers with support for making apps more accessible. Take note, iOS and Android differ slightly in their approaches, and thus the React Native implementations may vary by platform. -In addition to this documentation, you might find [this blog post](https://code.facebook.com/posts/435862739941212/making-react-native-apps-accessible/) about React Native accessibility to be useful. +In addition to this documentation, you might find [this blog post](https://engineering.fb.com/ios/making-react-native-apps-accessible/) about React Native accessibility to be useful. ## Making Apps Accessible @@ -76,9 +76,9 @@ Inverting screen colors is an Accessibility feature that makes the iPhone and iP #### accessibilityRole (iOS, Android) -> **Note:** Accessibility Role and Accessibility States are meant to be a cross-platform solution to replace `accessibilityTraits` and `accessibilityComponentType`, which will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. +`accessibilityRole` communicates the purpose of a component to the user of an assistive technology. -Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on Android the type of element that is focused on. To use, set the `accessibilityRole` property to one of the following strings: +`accessibilityRole` can be one of the following: - **none** Used when the element has no role. - **button** Used when the element should be treated as a button. @@ -91,43 +91,38 @@ Accessibility Role tells a person using either VoiceOver on iOS or TalkBack on A - **imagebutton** Used when the element should be treated as a button and is also an image. - **header** Used when an element acts as a header for a content section (e.g. the title of a navigation bar). - **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. +- **alert** Used when an element contains important text to be presented to the user. +- **checkbox** Used when an element represents a checkbox which can be checked, unchecked, or have mixed checked state. +- **combobox** Used when an element represents a combo box, which allows the user to select among several choices. +- **menu** Used when the component is a menu of choices. +- **menubar** Used when a component is a container of multiple menus. +- **menuitem** Used to represent an item within a menu. +- **progressbar** Used to represent a component which indicates progress of a task. +- **radio** Used to represent a radio button. +- **radiogroup** Used to represent a group of radio buttons. +- **scrollbar** Used to represent a scroll bar. +- **spinbutton** Used to represent a button which opens a list of choices. +- **switch** Used to represent a switch which can be turned on and off. +- **tab** Used to represent a tab. +- **tablist** Used to represent a list of tabs. +- **timer** Used to represent a timer. +- **toolbar** Used to represent a tool bar (a container of action buttons or components). #### accessibilityStates (iOS, Android) -> **Note:** > `accessibilityRole` and `accessibilityStates` are meant to be a cross-platform solution to replace `accessibilityTraits` and `accessibilityComponentType`, which will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. +Describes the current state of a component to the user of an assistive technology. -Accessibility State tells a person using either VoiceOver on iOS or TalkBack on Android the state of the element currently focused on. The state of the element can be set either to `selected` or `disabled` or both: +`accessibilityStates` is an array of values, and may include any of the following: - **selected** Used when the element is in a selected state. For example, a button is selected. - **disabled** Used when the element is disabled and cannot be interacted with. +- **checked** Used to indicate that a checkable element is currently checked. +- **unchecked** Used to indicate that a checkable element is not currently checked. +- **busy** Used to indicate that an element is currently busy. +- **expanded** Used to indicate that an expandable element is currently expanded. +- **collapsed** Used to indicate that an expandable element is currently collapsed. -To use, set the `accessibilityStates` to an array containing either `selected`, `disabled`, or both. - -#### accessibilityTraits (iOS) - -> **Note:** `accessibilityTraits` will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. - -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: - -- **none** Used when the element has no traits. -- **button** Used when the element should be treated as a button. -- **link** Used when the element should be treated as a link. -- **header** Used when an element acts as a header for a content section (e.g. the title of a navigation bar). -- **search** Used when the text field element should also be treated as a search field. -- **image** Used when the element should be treated as an image. Can be combined with button or link, for example. -- **selected** Used when the element is selected. For example, a selected row in a table or a selected button within a segmented control. -- **plays** Used when the element plays its own sound when activated. -- **key** Used when the element acts as a keyboard key. -- **text** Used when the element should be treated as static text that cannot change. -- **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches. For example, when Weather first launches, the element with today's weather conditions is marked with this trait. -- **disabled** Used when the control is not enabled and does not respond to user input. -- **frequentUpdates** Used when the element frequently updates its label or value, but too often to send notifications. Allows an accessibility client to poll for changes. A stopwatch would be an example. -- **startsMedia** Used when activating an element starts a media session (e.g. playing a movie, recording audio) that should not be interrupted by output from an assistive technology, like VoiceOver. -- **adjustable** Used when an element can be "adjusted" (e.g. a slider). -- **allowsDirectInteraction** Used when an element allows direct touch interaction for VoiceOver users (for example, a view representing a piano keyboard). -- **pageTurn** Informs VoiceOver that it should scroll to the next page when it finishes reading the contents of the element. +To use, set the `accessibilityStates` to an array containing the list of current states. #### accessibilityViewIsModal (iOS) @@ -153,23 +148,6 @@ Assign this property to a custom function which will be called when someone perf Assign this property to a custom function which will be called when someone performs the "escape" gesture, which is a two finger Z shaped gesture. An escape function should move back hierarchically in the user interface. This can mean moving up or back in a navigation hierarchy or dismissing a modal user interface. If the selected element does not have an `onAccessibilityEscape` function, the system will attempt to traverse up the view hierarchy until it finds a view that does or bonk to indicate it was unable to find one. -#### accessibilityComponentType (Android) - -> **Note:** > `accessibilityComponentType` will soon be deprecated. When possible, use `accessibilityRole` and `accessibilityStates` instead of `accessibilityTraits` and `accessibilityComponentType`. - -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. We support 'none', ‘button’, ‘radiobutton_checked’ and ‘radiobutton_unchecked’. - -```jsx - - - Press me! - - -``` - -In the above example, the TouchableWithoutFeedback is being announced by TalkBack as a native Button. - #### accessibilityLiveRegion (Android) When components dynamically change, we want TalkBack to alert the end user. This is made possible by the ‘accessibilityLiveRegion’ property. It can be set to ‘none’, ‘polite’ and ‘assertive’: @@ -210,6 +188,59 @@ In the case of two overlapping UI components with the same parent, default acces 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. +### Accessibility Actions + +Accessibility actions allow an assistive technology to programmatically invoke the actions of a component. In order to support accessibility actions, a component must do two things: + +- Define the list of actions it supports via the `accessibilityActions` property. +- Implement an `onAccessibilityAction` function to handle action requests. + +The `accessibilityActions` property should contain a list of action objects. Each action object should contain the following fields: + +| Name | Type | Required | +| ----- | ------ | -------- | +| name | string | Yes | +| label | string | No | + +Actions either represent standard actions, such as clicking a button or adjusting a slider, or custom actions specific to a given component such as deleting an email message. The `name` field is required for both standard and custom actions, but `label` is optional for standard actions. + +When adding support for standard actions, `name` must be one of the following: + +- `'magicTap'` - iOS only - While VoiceOver focus is on or inside the component, the user double tapped with two fingers. +- `'escape'` - iOS only - While VoiceOver focus is on or inside the component, the user performed a two finger scrub gesture (left, right, left). +- `'activate'` - Activate the component. Typically this should perform the same action as when the user touches or clicks the component when not using an assistive technology. This is generated when a screen reader user double taps the component. +- `'increment'` - Increment an adjustable component. On iOS, VoiceOver generates this action when the component has a role of `'adjustable'` and the user places focus on it and swipes upward. On Android, TalkBack generates this action when the user places accessibility focus on the component and presses the volume up button. +- `'decrement'` - Decrement an adjustable component. On iOS, VoiceOver generates this action when the component has a role of `'adjustable'` and the user places focus on it and swipes downward. On Android, TalkBack generates this action when the user places accessibility focus on the component and presses the volume down button. +- `'longpress'` - Android only - This action is generated when the user places accessibility focus on the component and double tap and holds one finger on the screen. Typically, this should perform the same action as when the user holds down one finger on the component while not using an assistive technology. + +The `label` field is optional for standard actions, and is often unused by assistive technologies. For custom actions, it is a localized string containing a description of the action to be presented to the user. + +To handle action requests, a component must implement an `onAccessibilityAction` function. The only argument to this function is an event containing the name of the action to perform. The below example from RNTester shows how to create a component which defines and handles several custom actions. + +```jsx + { + switch (event.nativeEvent.actionName) { + case 'cut': + Alert.alert('Alert', 'cut action success'); + break; + case 'copy': + Alert.alert('Alert', 'copy action success'); + break; + case 'paste': + Alert.alert('Alert', 'paste action success'); + break; + } + }} +/> +``` + ### Checking if a Screen Reader is Enabled The `AccessibilityInfo` API allows you to determine whether or not a screen reader is currently active. See the [AccessibilityInfo documentation](accessibilityinfo.md) for details. @@ -245,8 +276,31 @@ In the above example we've created a custom radio button that now behaves like a ## Testing VoiceOver Support (iOS) -To enable VoiceOver, go to the Settings app on your iOS device. Tap General, then Accessibility. There you will find many tools that people use to make their devices more usable, such as bolder text, increased contrast, and VoiceOver. +To enable VoiceOver, go to the Settings app on your iOS device (it's not available for simulator). Tap General, then Accessibility. There you will find many tools that people use to make their devices more usable, such as bolder text, increased contrast, and VoiceOver. To enable VoiceOver, tap on VoiceOver under "Vision" and toggle the switch that appears at the top. At the very bottom of the Accessibility settings, there is an "Accessibility Shortcut". You can use this to toggle VoiceOver by triple clicking the Home button. + +## Testing TalkBack Support (Android) + +To enable TalkBack, go to the Settings app on your Android device or emulator. Tap Accessibility, then TalkBack. Toggle the "Use service" switch to enable or disable it. + +P.S. Android emulator doesn’t have TalkBack by default. To install it: + +1. Download TalkBack file here: https://google-talkback.en.uptodown.com/android +2. Drag the downloaded `.apk` file into the emulator + +You can use the volume key shortcut to toggle TalkBack. To turn on the volume key shortcut, go to the Settings app, then Accessibility. At the top, turn on Volume key shortcut. + +To use the volume key shortcut, press both volume keys for 3 seconds to start an accessibility tool. + +Additionally, if you prefer, you can toggle TalkBack via command line with: + +``` +# disable +adb shell settings put secure enabled_accessibility_services com.android.talkback/com.google.android.marvin.talkback.TalkBackService + +# enable +adb shell settings put secure enabled_accessibility_services com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService +``` diff --git a/website/versioned_docs/version-0.5/animations.md b/website/versioned_docs/version-0.5/animations.md index 7f0f9f4ffff..7b73d696aed 100644 --- a/website/versioned_docs/version-0.5/animations.md +++ b/website/versioned_docs/version-0.5/animations.md @@ -12,56 +12,48 @@ React Native provides two complementary animation systems: [`Animated`](animatio The [`Animated`](animated.md) API is designed to make it very easy to concisely express a wide variety of interesting animation and interaction patterns in a very performant way. `Animated` focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and simple `start`/`stop` methods to control time-based animation execution. -`Animated` exports four animatable component types: `View`, `Text`, `Image`, and `ScrollView`, but you can also create your own using `Animated.createAnimatedComponent()`. +`Animated` exports six animatable component types: `View`, `Text`, `Image`, `ScrollView`, `FlatList` and `SectionList`, but you can also create your own using `Animated.createAnimatedComponent()`. For example, a container view that fades in when it is mounted may look like this: ```SnackPlayer -import React from 'react'; +import React, { useState, useEffect } from 'react'; import { Animated, Text, View } from 'react-native'; -class FadeInView extends React.Component { - state = { - fadeAnim: new Animated.Value(0), // Initial value for opacity: 0 - } +const FadeInView = (props) => { + const [fadeAdmin] = useState(new Animated.Value(0)) // Initial value for opacity: 0 - componentDidMount() { - Animated.timing( // Animate over time - this.state.fadeAnim, // The animated value to drive + React.useEffect(() => { + Animated.timing( + fadeAdmin, { - toValue: 1, // Animate to opacity: 1 (opaque) - duration: 10000, // Make it take a while + toValue: 1, + duration: 10000, } - ).start(); // Starts the animation - } - - render() { - let { fadeAnim } = this.state; - - return ( - - {this.props.children} - - ); - } + ).start(); + }, []) + + return ( + + {props.children} + + ); } // You can then use your `FadeInView` in place of a `View` in your components: -export default class App extends React.Component { - render() { - return ( - - - Fading in - - - ) - } +export default () => { + return ( + + + Fading in + + + ) } ``` @@ -69,8 +61,7 @@ Let's break down what's happening here. In the `FadeInView` constructor, a new ` When the component mounts, the opacity is set to 0. Then, an easing animation is started on the `fadeAnim` animated value, which will update all of its dependent mappings (in this case, just the opacity) on each frame as the value animates to the final value of 1. -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. +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. ### Configuring animations @@ -258,7 +249,7 @@ You may notice that there is no obvious way to read the current value while anim ### Using the native driver -The `Animated` API is designed to be serializable. By using the [native driver](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html), we send everything about the animation to native before starting the animation, allowing native code to perform the animation on the UI thread without having to go through the bridge on every frame. Once the animation has started, the JS thread can be blocked without affecting the animation. +The `Animated` API is designed to be serializable. By using the [native driver](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated), we send everything about the animation to native before starting the animation, allowing native code to perform the animation on the UI thread without having to go through the bridge on every frame. Once the animation has started, the JS thread can be blocked without affecting the animation. Using the native driver for normal animations is quite simple. Just add `useNativeDriver: true` to the animation config when starting it. @@ -319,8 +310,8 @@ While using transform styles such as `rotateY`, `rotateX`, and others ensure the The RNTester app has various examples of `Animated` in use: -- [AnimatedGratuitousApp](https://github.com/facebook/react-native/tree/master/RNTester/js/AnimatedGratuitousApp) -- [NativeAnimationsExample](https://github.com/facebook/react-native/blob/master/RNTester/js/NativeAnimationsExample.js) +- [AnimatedGratuitousApp](https://github.com/facebook/react-native/tree/master/RNTester/js/examples/Animated/AnimatedGratuitousApp) +- [NativeAnimationsExample](https://github.com/facebook/react-native/blob/master/RNTester/js/examples/NativeAnimation/NativeAnimationsExample.js) ## `LayoutAnimation` API @@ -415,4 +406,4 @@ As mentioned [in the Direct Manipulation section](direct-manipulation.md), `setN We could use this in the Rebound example to update the scale - this might be helpful if the component that we are updating is deeply nested and hasn't been optimized with `shouldComponentUpdate`. -If you find your animations with dropping frames (performing below 60 frames per second), look into using `setNativeProps` or `shouldComponentUpdate` to optimize them. Or you could run the animations on the UI thread rather than the JavaScript thread [with the useNativeDriver option](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated.html). You may also want to defer any computationally intensive work until after animations are complete, using the [InteractionManager](interactionmanager.md). You can monitor the frame rate by using the In-App Developer Menu "FPS Monitor" tool. +If you find your animations with dropping frames (performing below 60 frames per second), look into using `setNativeProps` or `shouldComponentUpdate` to optimize them. Or you could run the animations on the UI thread rather than the JavaScript thread [with the useNativeDriver option](http://facebook.github.io/react-native/blog/2017/02/14/using-native-driver-for-animated). You may also want to defer any computationally intensive work until after animations are complete, using the [InteractionManager](interactionmanager.md). You can monitor the frame rate by using the In-App Developer Menu "FPS Monitor" tool. diff --git a/website/versioned_docs/version-0.5/app-extensions.md b/website/versioned_docs/version-0.5/app-extensions.md index a27630bec52..bf6f30e1dd2 100644 --- a/website/versioned_docs/version-0.5/app-extensions.md +++ b/website/versioned_docs/version-0.5/app-extensions.md @@ -10,7 +10,7 @@ App extensions let you provide custom functionality and content outside of your As these extensions are loaded outside of the regular app sandbox, it's highly likely that several of these app extensions will be loaded simultaneously. As you might expect, these extensions have small memory usage limits. Keep these in mind when developing your app extensions. It's always highly recommended to test your application on an actual device, and more so when developing app extensions: too frequently, developers find that their extension works just fine in the iOS Simulator, only to get user reports that their extension is not loading on actual devices. -We highly recommend that you watch Conrad Kramer's talk on [Memory Use in Extensions](https://cocoaheads.tv/memory-use-in-extensions-by-conrad-kramer/) to learn more about this topic. +We highly recommend that you watch Conrad Kramer's talk on [Memory Use in Extensions](https://www.youtube.com/watch?v=GqXMqn6MXrM) to learn more about this topic. ### Today widget diff --git a/website/versioned_docs/version-0.5/communication-ios.md b/website/versioned_docs/version-0.5/communication-ios.md index 4b3fe1a4c86..2afc10b0453 100644 --- a/website/versioned_docs/version-0.5/communication-ios.md +++ b/website/versioned_docs/version-0.5/communication-ios.md @@ -35,9 +35,9 @@ RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge ```jsx import React from 'react'; -import {AppRegistry, View, Image} from 'react-native'; +import {View, Image} from 'react-native'; -class ImageBrowserApp extends React.Component { +export default class ImageBrowserApp extends React.Component { renderImage(imgURI) { return ; } @@ -45,8 +45,6 @@ class ImageBrowserApp extends React.Component { return {this.props.images.map(this.renderImage)}; } } - -AppRegistry.registerComponent('ImageBrowserApp', () => ImageBrowserApp); ``` `RCTRootView` also provides a read-write property `appProperties`. After `appProperties` is set, the React Native app is re-rendered with new properties. The update is only performed when the new updated properties differ from the previous ones. diff --git a/website/versioned_docs/version-0.5/components-and-apis.md b/website/versioned_docs/version-0.5/components-and-apis.md index 9ce293713f2..af38cd9a26a 100644 --- a/website/versioned_docs/version-0.5/components-and-apis.md +++ b/website/versioned_docs/version-0.5/components-and-apis.md @@ -105,10 +105,6 @@ Many of the following components provide wrappers for commonly used UIKit classe

ImagePickerIOS

Renders a image picker on iOS.

-
-

NavigatorIOS

-

A wrapper around UINavigationController, enabling you to implement a navigation stack.

-

ProgressViewIOS

Renders a UIProgressView on iOS.

@@ -187,10 +183,6 @@ These components may come in handy for certain applications. For an exhaustive l

Animated

A library for creating fluid, powerful animations that are easy to build and maintain.

-
-

CameraRoll

-

Provides access to the local camera roll / gallery.

-

Clipboard

Provides an interface for setting and getting content from the clipboard on both iOS and Android.

diff --git a/website/versioned_docs/version-0.5/debugging.md b/website/versioned_docs/version-0.5/debugging.md index fa2b6bd3ec8..a839a4d548b 100644 --- a/website/versioned_docs/version-0.5/debugging.md +++ b/website/versioned_docs/version-0.5/debugging.md @@ -24,7 +24,7 @@ Instead of recompiling your app every time you make a change, you can reload you You can speed up your development times by having your app reload automatically any time your code changes. Automatic reloading can be enabled by selecting "Enable Live Reload" from the Developer Menu. -You may even go a step further and keep your app running as new versions of your files are injected into the JavaScript bundle automatically by enabling [Hot Reloading](https://facebook.github.io/react-native/blog/2016/03/24/introducing-hot-reloading.html) from the Developer Menu. This will allow you to persist the app's state through reloads. +You may even go a step further and keep your app running as new versions of your files are injected into the JavaScript bundle automatically by enabling [Hot Reloading](https://facebook.github.io/react-native/blog/2016/03/24/introducing-hot-reloading) from the Developer Menu. This will allow you to persist the app's state through reloads. > There are some instances where hot reloading cannot be implemented perfectly. If you run into any issues, use a full reload to reset your app. @@ -89,7 +89,7 @@ However, there are some disadvantages: ## React Developer Tools -You can use [the standalone version of React Developer Tools](https://github.com/facebook/react-devtools/tree/master/packages/react-devtools) to debug the React component hierarchy. To use it, install the `react-devtools` package globally: +You can use [the standalone version of React Developer Tools](https://github.com/facebook/react/tree/master/packages/react-devtools) to debug the React component hierarchy. To use it, install the `react-devtools` package globally: ``` npm install -g react-devtools diff --git a/website/versioned_docs/version-0.5/direct-manipulation.md b/website/versioned_docs/version-0.5/direct-manipulation.md index 5229742d2ee..b759df48f30 100644 --- a/website/versioned_docs/version-0.5/direct-manipulation.md +++ b/website/versioned_docs/version-0.5/direct-manipulation.md @@ -8,7 +8,7 @@ It is sometimes necessary to make changes directly to a component without using > Use setNativeProps when frequent re-rendering creates a performance bottleneck > -> Direct manipulation will not be a tool that you reach for frequently; you will typically only be using it for creating continuous animations to avoid the overhead of rendering the component 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](http://facebook.github.io/react/advanced-performance.md#shouldcomponentupdate-in-action). +> Direct manipulation will not be a tool that you reach for frequently; you will typically only be using it for creating continuous animations to avoid the overhead of rendering the component 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](https://reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action). ## setNativeProps with TouchableOpacity @@ -55,7 +55,7 @@ render() { This is computationally intensive compared to the original example - React needs to re-render the component hierarchy each time the opacity changes, even though other properties of the view and its children haven't changed. Usually this overhead isn't a concern but when performing continuous animations and responding to gestures, judiciously optimizing your components can improve your animations' fidelity. -If you look at the implementation of `setNativeProps` in [NativeMethodsMixin](https://github.com/facebook/react-native/blob/master/Libraries/Renderer/oss/ReactNativeRenderer-prod.js) 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](https://github.com/facebook/react-native/blob/fb2ec1ea47c53c2e7b873acb1cb46192ac74274e/Libraries/Renderer/oss/ReactNativeRenderer-prod.js#L5793-L5813). +If you look at the implementation of `setNativeProps` in [NativeMethodsMixin](https://github.com/facebook/react-native/blob/master/Libraries/Renderer/implementations/ReactNativeRenderer-prod.js) 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](https://github.com/facebook/react-native/blob/fb2ec1ea47c53c2e7b873acb1cb46192ac74274e/Libraries/Renderer/oss/ReactNativeRenderer-prod.js#L5793-L5813). ## Composite components and setNativeProps @@ -140,10 +140,10 @@ export default class App extends React.Component { render() { return ( - + this._textInput = component} - style={{height: 50, flex: 1, marginHorizontal: 20, borderWidth: 1, borderColor: '#ccc'}} + style={{height: 50, width: 200, marginHorizontal: 20, borderWidth: 1, borderColor: '#ccc'}} /> Clear text @@ -190,7 +190,7 @@ Determines the location of the given view in the window and returns the values v ### measureLayout(relativeToNativeNode, onSuccess, onFail) -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. +Like `measure()`, but measures the view relative to 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 `findNodeHandle(component)`. diff --git a/website/versioned_docs/version-0.5/flexbox.md b/website/versioned_docs/version-0.5/flexbox.md index 236e6226c6a..b531fa1e890 100644 --- a/website/versioned_docs/version-0.5/flexbox.md +++ b/website/versioned_docs/version-0.5/flexbox.md @@ -10,13 +10,31 @@ You will normally use a combination of `flexDirection`, `alignItems`, and `justi > Flexbox works the same way in React Native as it does in CSS on the web, with a few exceptions. The defaults are different, with `flexDirection` defaulting to `column` instead of `row`, and the `flex` parameter only supporting a single number. +### Flex + +[`flex`](https://facebook.github.io/react-native/docs/layout-props#flex) will define how your items are going to **“fill”** over the available space along your main axis. Space will be divided according to each element's flex property. + +In the following example the red, yellow and the green views are all children in the container view that has `flex: 1` set. The red view uses `flex: 1` , the yellow view uses `flex: 2` and the green view uses `flex: 3` . **1+2+3 = 6** which means that the red view will get `1/6` of the space, the yellow `2/6` of the space and the green `3/6` of the space. + +![Flex](https://cdn-images-1.medium.com/max/800/1*PhCFmO5tYX_sZSyCd4vO3w.png) + #### Flex Direction -Adding `flexDirection` to a component's `style` determines the **primary axis** of its layout. Should the children be organized horizontally (`row`) or vertically (`column`)? The default is `column`. +[`flexDirection`](https://facebook.github.io/react-native/docs/layout-props#flexdirection) controls the direction in which the children of a node are laid out. This is also referred to as the _main axis_. The cross axis is the axis perpendicular to the main axis, or the axis which the wrapping lines are laid out in. + +- `row` Align children from left to right. If wrapping is enabled then the next line will start under the first item on the left of the container. + +- `column` (**default value**) Align children from top to bottom. If wrapping is enabled then the next line will start to the left first item on the top of the container. + +- `row-reverse` Align children from right to left. If wrapping is enabled then the next line will start under the first item on the right of the container. + +- `column-reverse` Align children from bottom to top. If wrapping is enabled then the next line will start to the left first item on the bottom of the container. + +LEARN MORE [HERE](https://yogalayout.com/docs/flex-direction) -```SnackPlayer +```SnackPlayer name=Flex%20Direction import React, { Component } from 'react'; -import { AppRegistry, View } from 'react-native'; +import { View } from 'react-native'; export default class FlexDirectionBasics extends Component { render() { @@ -30,18 +48,39 @@ export default class FlexDirectionBasics extends Component { ); } }; - -// skip this line if using Create React Native App -AppRegistry.registerComponent('AwesomeProject', () => FlexDirectionBasics); ``` +![Flex Direction](https://cdn-images-1.medium.com/max/800/1*rA7IbuUsJWsx6evKAsabVw.png) + +### Layout Direction + +Layout direction specifies the direction in which children and text in a hierarchy should be laid out. Layout direction also affects what edge `start` and `end` refer to. By default React Native lays out with LTR layout direction. In this mode `start` refers to left and `end` refers to right. + +- `LTR` (**default value**) Text and children are laid out from left to right. Margin and padding applied the start of an element are applied on the left side. + +- `RTL` Text and children are laid out from right to left. Margin and padding applied the start of an element are applied on the right side. + #### Justify Content -Adding `justifyContent` to a component's style determines the **distribution** of children along the **primary axis**. Should children be distributed at the start, the center, the end, or spaced evenly? Available options are `flex-start`, `center`, `flex-end`, `space-around`, `space-between` and `space-evenly`. +[`justifyContent`](https://facebook.github.io/react-native/docs/layout-props#justifycontent) describes how to align children within the main axis of their container. For example, you can use this property to center a child horizontally within a container with `flexDirection` set to `row` or vertically within a container with `flexDirection` set to `column`. + +- `flex-start`(**default value**) Align children of a container to the start of the container's main axis. + +- `flex-end` Align children of a container to the end of the container's main axis. + +- `center` Align children of a container in the center of the container's main axis. -```SnackPlayer +- `space-between` Evenly space of children across the container's main axis, distributing remaining space between the children. + +- `space-around` Evenly space of children across the container's main axis, distributing remaining space around the children. Compared to `space-between` using `space-around` will result in space being distributed to the beginning of the first child and end of the last child. + +- `space-evenly` Evenly distributed within the alignment container along the main axis. The spacing between each pair of adjacent items, the main-start edge and the first item, and the main-end edge and the last item, are all exactly the same. + +LEARN MORE [HERE](https://yogalayout.com/docs/justify-content) + +```SnackPlayer name=Justify%20Content import React, { Component } from 'react'; -import { AppRegistry, View } from 'react-native'; +import { View } from 'react-native'; export default class JustifyContentBasics extends Component { render() { @@ -60,20 +99,31 @@ export default class JustifyContentBasics extends Component { ); } }; - -// skip this line if using Create React Native App -AppRegistry.registerComponent('AwesomeProject', () => JustifyContentBasics); ``` +![Justify Content](https://cdn-images-1.medium.com/max/800/1*i5TVlme-TisAVvD5ax2yPA.png) + #### Align Items -Adding `alignItems` to a component's style determines the **alignment** of children along the **secondary axis** (if the primary axis is `row`, then the secondary is `column`, and vice versa). Should children be aligned at the start, the center, the end, or stretched to fill? Available options are `flex-start`, `center`, `flex-end`, and `stretch`. +[`alignItems`](https://facebook.github.io/react-native/docs/layout-props#alignitems) describes how to align children along the cross axis of their container. Align items is very similar to `justifyContent` but instead of applying to the main axis, `alignItems` applies to the cross axis. + +- `stretch` (**default value**) Stretch children of a container to match the `height` of the container's cross axis. + +- `flex-start` Align children of a container to the start of the container's cross axis. + +- `flex-end` Align children of a container to the end of the container's cross axis. + +- `center` Align children of a container in the center of the container's cross axis. + +- `baseline` Align children of a container along a common baseline. Individual children can be set to be the reference baseline for their parents. > For `stretch` to have an effect, children must not have a fixed dimension along the secondary axis. In the following example, setting `alignItems: stretch` does nothing until the `width: 50` is removed from the children. -```SnackPlayer +LEARN MORE [HERE](https://yogalayout.com/docs/align-items) + +```SnackPlayer name=Align%20Items import React, { Component } from 'react'; -import { AppRegistry, View } from 'react-native'; +import { View } from 'react-native'; export default class AlignItemsBasics extends Component { render() { @@ -94,13 +144,86 @@ export default class AlignItemsBasics extends Component { ); } }; - -// skip this line if using Create React Native App -AppRegistry.registerComponent('AwesomeProject', () => AlignItemsBasics); ``` +![Align Items](https://cdn-images-1.medium.com/max/800/1*evkM7zfxt-9p-HJ1M0Bh2g.png) + +### Align Self + +[`alignSelf`](https://facebook.github.io/react-native/docs/layout-props#alignself) has the same options and effect as `alignItems` but instead of affecting the children within a container, you can apply this property to a single child to change its alignment within its parent. `alignSelf` overrides any option set by the parent with `alignItems`. + +![Align Self](https://cdn-images-1.medium.com/max/800/1*J1JCoKwLCokX9JXVBvP71g.png) + +### Align Content + +[alignContent](https://facebook.github.io/react-native/docs/layout-props#aligncontent) defines the distribution of lines along the cross-axis. This only has effect when items are wrapped to multiple lines using `flexWrap`. + +- `flex-start` (**default value**) Align wrapped lines to the start of the container's cross axis. + +- `flex-end` Align wrapped lines to the end of the container's cross axis. + +- `stretch` wrapped lines to match the height of the container's cross axis. + +- `center` Align wrapped lines in the center of the container's cross axis. + +- `space-between` Evenly space wrapped lines across the container's main axis, distributing remaining space between the lines. + +- `space-around` Evenly space wrapped lines across the container's main axis, distributing remaining space around the lines. Compared to space between using space around will result in space being distributed to the begining of the first lines and end of the last line. + +LEARN MORE [HERE](https://yogalayout.com/docs/align-content) + +![Align Content](https://cdn-images-1.medium.com/max/800/1*cC2XFyCF_igp20Ombt4wBw.png) + +### Flex Wrap + +The [`flexWrap`](https://facebook.github.io/react-native/docs/layout-props#flexwrap) property is set on containers and controls what happens when children overflow the size of the container along the main axis. By default children are forced into a single line (which can shrink elements). If wrapping is allowed items are wrapped into multiple lines along the main axis if needed. + +When wrapping lines `alignContent` can be used to specify how the lines are placed in the container. learn more [here](https://yogalayout.com/docs/flex-wrap) + +![Flex Wrap](https://cdn-images-1.medium.com/max/800/1*_7v4uQhSsuCn1cfeOMVfrA.png) + +### Flex Basis, Grow, and Shrink + +- [`flexGrow`](https://facebook.github.io/react-native/docs/layout-props#flexgrow) describes how any space within a container should be distributed among its children along the main axis. After laying out its children, a container will distribute any remaining space according to the flex grow values specified by its children. + + flexGrow accepts any floating point value >= 0, with 0 being the default value. A container will distribute any remaining space among its children weighted by the child’s flex grow value. + +- [`flexShrink`](https://facebook.github.io/react-native/docs/layout-props#flexshrink) describes how to shrink children along the main axis in the case that the total size of the children overflow the size of the container on the main axis. Flex shrink is very similar to flex grow and can be thought of in the same way if any overflowing size is considered to be negative remaining space. These two properties also work well together by allowing children to grow and shrink as needed. + + Flex shrink accepts any floating point value >= 0, with 1 being the default value. A container will shrink its children weighted by the child’s flex shrink value. + +- [`flexBasis`](https://facebook.github.io/react-native/docs/layout-props#flexbasis) is an axis-independent way of providing the default size of an item along the main axis. Setting the flex basis of a child is similar to setting the `width` of that child if its parent is a container with `flexDirection: row` or setting the `height` of a child if its parent is a container with `flexDirection: column`. The flex basis of an item is the default size of that item, the size of the item before any flex grow and flex shrink calculations are performed. + +LEARN MORE [HERE](https://yogalayout.com/docs/flex) + +### Width and Height + +The `width` property in Yoga specifies the width of the element's content area. Similarly height property specifies the `height` of the element's content area. + +Both `width` and `height` can take following values: + +- `auto` Is the **default Value**, React Native calculates the width/height for the element based on its content, whether that is other children, text, or an image. + +- `pixels` Defines the width/height in absolute pixels. Depending on other styles set on the component, this may or may not be the final dimension of the node. + +- `percentage` Defines the width or height in percentage of its parent's width or height respectively. + +### Absolute & Relative Layout + +The `position` type of an element defines how it is positioned within its parent. + +`relative` (**default value**) By default an element is positioned relatively. This means an element is positioned according to the normal flow of the layout, and then offset relative to that position based on the values of `top`, `right`, `bottom`, and `left`. The offset does not affect the position of any sibling or parent elements. + +`absolute` When positioned absolutely an element doesn't take part in the normal layout flow. It is instead laid out independent of its siblings. The position is determined based on the `top`, `right`, `bottom`, and `left` values. + +![Absolute & Relative Layoutp](https://cdn-images-1.medium.com/max/800/1*NlPeRQCQK3Vb5nyjL0Mqxw.png) + #### Going Deeper +Check out the interactive [yoga playground](https://yogalayout.com/playground) that you can use to get a better understanding of flexbox. + We've covered the basics, but there are many other styles you may need for layouts. The full list of props that control layout is documented [here](./layout-props.md). We're getting close to being able to build a real application. One thing we are still missing is a way to take user input, so let's move on to [learn how to handle text input with the TextInput component](handling-text-input.md). + +See some examples from [Wix Engineers](https://medium.com/wix-engineering/the-full-react-native-layout-cheat-sheet-a4147802405c): diff --git a/website/versioned_docs/version-0.5/getting-started.md b/website/versioned_docs/version-0.5/getting-started.md index 031a6711cfe..c2e04056c11 100644 --- a/website/versioned_docs/version-0.5/getting-started.md +++ b/website/versioned_docs/version-0.5/getting-started.md @@ -6,9 +6,9 @@ original_id: getting-started This page will help you install and build your first React Native app. If you already have React Native installed, you can skip ahead to the [Tutorial](tutorial.md). -If you are coming from a web background, the easiest way to get started with React Native is with Expo tools because they allow you to start a project without installing and configuring Xcode or Android Studio. Expo CLI sets up a development environment on your local machine and you can be writing a React Native app within minutes. For instant development, you can use [Snack](https://snack.expo.io/) to try React Native out directly in your web browser. +If you are new to mobile development, the easiest way to get started is with Expo CLI. Expo is a set of tools built around React Native and, while it has many [features](https://expo.io/features), the most relevant feature for us right now is that it can get you writing a React Native app within minutes. You will only need a recent version of Node.js and a phone or emulator. If you'd like to try out React Native directly in your web browser before installing any tools, you can try out [Snack](https://snack.expo.io/). -If you are familiar with native development, you will likely want to use React Native CLI. It requires Xcode or Android Studio to get started. If you already have one of these tools installed, you should be able to get up and running within a few minutes. If they are not installed, you should expect to spend about an hour installing and configuring them. +If you are already familiar with mobile development, you may want to use React Native CLI. It requires Xcode or Android Studio to get started. If you already have one of these tools installed, you should be able to get up and running within a few minutes. If they are not installed, you should expect to spend about an hour installing and configuring them.
    @@ -23,7 +23,7 @@ This page will help you install and build your first React Native app. If you al -Assuming that you have [Node 10+](https://nodejs.org/en/download/) installed, you can use npm to install the Expo CLI command line utility: +Assuming that you have [Node 10 LTS](https://nodejs.org/en/download/) or greater installed, you can use npm to install the Expo CLI command line utility: ```sh npm install -g expo-cli @@ -40,21 +40,21 @@ npm start # you can also use: expo start This will start a development server for you. -## Running your React Native application +

    Running your React Native application

    Install the [Expo](https://expo.io) client app on your iOS or Android phone and connect to the same wireless network as your computer. On Android, use the Expo app to scan the QR code from your terminal to open your project. On iOS, follow on-screen instructions to get a link. -### Modifying your app +

    Modifying your app

    Now that you have successfully run the app, let's modify it. Open `App.js` in your text editor of choice and edit some lines. The application should reload automatically once you save your changes. -### That's it! +

    That's it!

    Congratulations! You've successfully run and modified your first React Native app.
    -## Now what? +

    Now what?

    Expo also has [docs](https://docs.expo.io) you can reference if you have questions specific to the tool. You can also ask for help at [Expo forums](https://forums.expo.io). @@ -67,54 +67,54 @@ If you have a problem with Expo, before creating a new issue, please see if ther If you're curious to learn more about React Native, continue on to the [Tutorial](tutorial.md). -### Running your app on a simulator or virtual device +

    Running your app on a simulator or virtual device

    -Expo CLI makes it really easy to run your React Native app on a physical device without setting up a development environment. If you want to run your app on the iOS Simulator or an Android Virtual Device, please refer to the instructions for building projects with native code to learn how to install Xcode or set up your Android development environment. +Expo CLI makes it really easy to run your React Native app on a physical device without setting up a development environment. If you want to run your app on the iOS Simulator or an Android Virtual Device, please refer to the instructions for "React Native CLI Quickstart" to learn how to install Xcode or set up your Android development environment. Once you've set these up, you can launch your app on an Android Virtual Device by running `npm run android`, or on the iOS Simulator by running `npm run ios` (macOS only). -### Caveats +

    Caveats

    Because you don't build any native code when using Expo to create a project, it's not possible to include custom native modules beyond the React Native APIs and components that are available in the Expo client app. -If you know that you'll eventually need to include your own native code, Expo is still a good way to get started. In that case you'll just need to "[eject](https://docs.expo.io/versions/latest/expokit/eject)" eventually to create your own native builds. If you do eject, the "Building Projects with Native Code" instructions will be required to continue working on your project. +If you know that you'll eventually need to include your own native code, Expo is still a good way to get started. In that case you'll just need to "[eject](https://docs.expo.io/versions/latest/expokit/eject)" eventually to create your own native builds. If you do eject, the "React Native CLI Quickstart" instructions will be required to continue working on your project. Expo CLI configures your project to use the most recent React Native version that is supported by the Expo client app. The Expo client app usually gains support for a given React Native version about a week after the React Native version is released as stable. You can check [this document](https://docs.expo.io/versions/latest/sdk/#sdk-version) to find out what versions are supported. -If you're integrating React Native into an existing project, you'll want to skip Expo CLI and go directly to setting up the native build environment. Select "Building Projects with Native Code" above for instructions on configuring a native build environment for React Native. +If you're integrating React Native into an existing project, you'll want to skip Expo CLI and go directly to setting up the native build environment. Select "React Native CLI Quickstart" above for instructions on configuring a native build environment for React Native. -

    Follow these instructions if you need to build native code in your project. For example, if you are integrating React Native into an existing application, or if you "ejected" from Expo or Create React Native App, you'll need this section.

    +

    Follow these instructions if you need to build native code in your project. For example, if you are integrating React Native into an existing application, or if you "ejected" from Expo, you'll need this section.

    The instructions are a bit different depending on your development operating system, and whether you want to start developing for iOS or Android. If you want to develop for both iOS and Android, that's fine - you just have to pick one to start with, since the setup is a bit different.
    Development OS: - - - +
    Target OS: - - +
    -## Unsupported +

    Unsupported

    -

    A Mac is required to build projects with native code for iOS. You can follow the Quick Start to learn how to build your app using Expo instead.

    +

    A Mac is required to build projects with native code for iOS. You can follow the Quick Start to learn how to build your app using Expo instead.

    -## Installing dependencies +

    Installing dependencies

    You will need Node, Watchman, the React Native command line interface, and Xcode. @@ -122,19 +122,19 @@ While you can use any editor of your choice to develop your app, you will need t -## Installing dependencies +

    Installing dependencies

    You will need Node, Watchman, the React Native command line interface, a JDK, and Android Studio. -## Installing dependencies +

    Installing dependencies

    You will need Node, the React Native command line interface, a JDK, and Android Studio. -## Installing dependencies +

    Installing dependencies

    You will need Node, the React Native command line interface, Python2, a JDK, and Android Studio. @@ -144,28 +144,33 @@ While you can use any editor of your choice to develop your app, you will need t -### Node, Watchman +

    Node, Watchman, JDK

    -We recommend installing Node and Watchman using [Homebrew](http://brew.sh/). Run the following commands in a Terminal after installing Homebrew: +We recommend installing Node, Watchman, and JDK using [Homebrew](http://brew.sh/). Run the following commands in a Terminal after installing Homebrew: ``` +brew install yarn brew install node brew install watchman +brew tap AdoptOpenJDK/openjdk +brew cask install adoptopenjdk8 ``` If you have already installed Node on your system, make sure it is Node 8.3 or newer. [Watchman](https://facebook.github.io/watchman) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance. +If you have already installed JDK on your system, make sure it is JDK 8 or newer. + -### Node +

    Node

    Follow the [installation instructions for your Linux distribution](https://nodejs.org/en/download/package-manager/) to install Node 8.3 or newer. -### Node, Python2, JDK +

    Node, Python2, JDK

    We recommend installing Node and Python2 via [Chocolatey](https://chocolatey.org), a popular package manager for Windows. @@ -183,7 +188,7 @@ If you have already installed Node on your system, make sure it is Node 8.3 or n -### The React Native CLI +

    The React Native CLI

    Node comes with npm, which lets you install the React Native command line interface. @@ -197,7 +202,7 @@ npm install -g react-native-cli -### The React Native CLI +

    The React Native CLI

    Node comes with npm, which lets you install the React Native command line interface. @@ -211,33 +216,33 @@ npm install -g react-native-cli -### Xcode +

    Xcode

    The easiest way to install Xcode is via the [Mac App Store](https://itunes.apple.com/us/app/xcode/id497799835?mt=12). Installing Xcode will also install the iOS Simulator and all the necessary tools to build your iOS app. If you have already installed Xcode on your system, make sure it is version 9.4 or newer. -#### Command Line Tools +

    Command Line Tools

    You will also need to install the Xcode Command Line Tools. Open Xcode, then choose "Preferences..." from the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown. ![Xcode Command Line Tools](/react-native/docs/assets/GettingStartedXcodeCommandLineTools.png) - + -### Java Development Kit +

    Java Development Kit

    -React Native requires a recent version of the Java SE Development Kit (JDK). [Download and install Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) if needed. You can also use [OpenJDK 8](http://openjdk.java.net/install/) as an alternative. +React Native requires version 8 of the Java SE Development Kit (JDK). You may download and install [OpenJDK](http://openjdk.java.net) from [AdoptOpenJDK](https://adoptopenjdk.net/) or your system packager. You may also [Download and install Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) if desired. -### Android development environment +

    Android development environment

    Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. -#### 1. Install Android Studio +

    1. Install Android Studio

    [Download and install Android Studio](https://developer.android.com/studio/index.html). Choose a "Custom" setup when prompted to select an installation type. Make sure the boxes next to all of the following are checked: @@ -262,7 +267,7 @@ Then, click "Next" to install all of these components. Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. -#### 2. Install the Android SDK +

    2. Install the Android SDK

    Android Studio installs the latest Android SDK by default. Building a React Native app with native code, however, requires the `Android 9 (Pie)` SDK in particular. Additional Android SDKs can be installed through the SDK Manager in Android Studio. @@ -289,13 +294,13 @@ Next, select the "SDK Tools" tab and check the box next to "Show Package Details Finally, click "Apply" to download and install the Android SDK and related build tools. -#### 3. Configure the ANDROID_HOME environment variable +

    3. Configure the ANDROID_HOME environment variable

    The React Native tools require some environment variables to be set up in order to build apps with native code. -Add the following lines to your `$HOME/.bash_profile` config file: +Add the following lines to your `$HOME/.bash_profile` or `$HOME/.bashrc` config file: @@ -341,7 +346,7 @@ You can find the actual location of the SDK in the Android Studio "Preferences" Open a new Command Prompt window to ensure the new environment variable is loaded before proceeding to the next step. -#### 4. Add platform-tools to Path +

    4. Add platform-tools to Path

    Open the System pane under **System and Security** in the Windows Control Panel, then click on **Change settings...**. Open the **Advanced** tab and click on **Environment Variables...**. Select the **Path** variable, then click **Edit**. Click **New** and add the path to platform-tools to the list. @@ -353,7 +358,7 @@ c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk\platform-tools -### Watchman +

    Watchman

    Follow the [Watchman installation guide](https://facebook.github.io/watchman/docs/install.html#buildinstall) to compile and install Watchman from source. @@ -361,7 +366,7 @@ Follow the [Watchman installation guide](https://facebook.github.io/watchman/doc -## Creating a new application +

    Creating a new application

    Use the React Native command line interface to generate a new React Native project called "AwesomeProject": @@ -371,9 +376,9 @@ react-native init AwesomeProject This is not necessary if you are integrating React Native into an existing application, if you "ejected" from Expo (or Create React Native App), or if you're adding iOS support to an existing React Native project (see [Platform Specific Code](platform-specific-code.md)). You can also use a third-party CLI to init your React Native app, such as [Ignite CLI](https://github.com/infinitered/ignite). -### [Optional] Using a specific version +

    [Optional] Using a specific version

    -If you want to start a new project with a specifc React Native version, you can use the `--version` argument: +If you want to start a new project with a specific React Native version, you can use the `--version` argument: ``` react-native init AwesomeProject --version X.XX.X @@ -385,7 +390,7 @@ react-native init AwesomeProject --version react-native@next -## Creating a new application +

    Creating a new application

    Use the React Native command line interface to generate a new React Native project called "AwesomeProject": @@ -395,9 +400,9 @@ react-native init AwesomeProject This is not necessary if you are integrating React Native into an existing application, if you "ejected" from Create React Native App, or if you're adding Android support to an existing React Native project (see [Platform Specific Code](platform-specific-code.md)). You can also use a third-party CLI to init your React Native app, such as [Ignite CLI](https://github.com/infinitered/ignite). -### [Optional] Using a specific version +

    [Optional] Using a specific version

    -If you want to start a new project with a specifc React Native version, you can use the `--version` argument: +If you want to start a new project with a specific React Native version, you can use the `--version` argument: ``` react-native init AwesomeProject --version X.XX.X @@ -409,17 +414,17 @@ react-native init AwesomeProject --version react-native@next -## Preparing the Android device +

    Preparing the Android device

    You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. Either way, you will need to prepare the device to run Android apps for development. -### Using a physical device +

    Using a physical device

    If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable and following the instructions [here](running-on-device.md). -### Using a virtual device +

    Using a virtual device

    If you use Android Studio to open `./AwesomeProject/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: @@ -445,7 +450,7 @@ Click "Next" then "Finish" to create your AVD. At this point you should be able -## Running your React Native application +

    Running your React Native application

    Run `react-native run-ios` inside your React Native project folder: @@ -458,17 +463,17 @@ You should see your new app running in the iOS Simulator shortly. ![AwesomeProject on iOS](/react-native/docs/assets/GettingStartediOSSuccess.png) -`react-native run-ios` is just one way to run your app. You can also run it directly from within Xcode or [Nuclide](https://nuclide.io/). +`react-native run-ios` is just one way to run your app. You can also run it directly from within Xcode. > If you can't get this to work, see the [Troubleshooting](troubleshooting.md#content) page. -### Running on a device +

    Running on a device

    The above command will automatically run your app on the iOS Simulator by default. If you want to run the app on an actual physical iOS device, please follow the instructions [here](running-on-device.md). -## Running your React Native application +

    Running your React Native application

    Run `react-native run-android` inside your React Native project folder: @@ -489,13 +494,13 @@ If everything is set up correctly, you should see your new app running in your A -`react-native run-android` is just one way to run your app - you can also run it directly from within Android Studio or [Nuclide](https://nuclide.io/). +`react-native run-android` is just one way to run your app - you can also run it directly from within Android Studio. > If you can't get this to work, see the [Troubleshooting](troubleshooting.md#content) page. -### Modifying your app +

    Modifying your app

    Now that you have successfully run the app, let's modify it. @@ -511,7 +516,7 @@ Now that you have successfully run the app, let's modify it. -### Modifying your app +

    Modifying your app

    Now that you have successfully run the app, let's modify it. @@ -520,7 +525,7 @@ Now that you have successfully run the app, let's modify it. -### That's it! +

    That's it!

    Congratulations! You've successfully run and modified your first React Native app. @@ -528,7 +533,7 @@ Congratulations! You've successfully run and modified your first React Native ap -### That's it! +

    That's it!

    Congratulations! You've successfully run and modified your first React Native app. @@ -536,7 +541,7 @@ Congratulations! You've successfully run and modified your first React Native ap -## Now what? +

    Now what?

    - Turn on [Live Reload](debugging.md#reloading-javascript) in the Developer Menu. Your app will now reload automatically whenever you save any changes! @@ -546,7 +551,7 @@ If you're curious to learn more about React Native, continue on to the [Tutorial -## Now what? +

    Now what?

    - Turn on [Live Reload](debugging.md#reloading-javascript) in the Developer Menu. Your app will now reload automatically whenever you save any changes! diff --git a/website/versioned_docs/version-0.5/handling-text-input.md b/website/versioned_docs/version-0.5/handling-text-input.md index 70622bf5993..e7cd81c83d7 100644 --- a/website/versioned_docs/version-0.5/handling-text-input.md +++ b/website/versioned_docs/version-0.5/handling-text-input.md @@ -8,9 +8,9 @@ original_id: handling-text-input For example, let's say that as the user types, you're translating their words into a different language. In this new language, every single word is written the same way: 🍕. So the sentence "Hello there Bob" would be translated as "🍕🍕🍕". -```SnackPlayer +```SnackPlayer name=Handling%20Text%20Input import React, { Component } from 'react'; -import { AppRegistry, Text, TextInput, View } from 'react-native'; +import { Text, TextInput, View } from 'react-native'; export default class PizzaTranslator extends Component { constructor(props) { @@ -25,6 +25,7 @@ export default class PizzaTranslator extends Component { style={{height: 40}} placeholder="Type here to translate!" onChangeText={(text) => this.setState({text})} + value={this.state.text} /> {this.state.text.split(' ').map((word) => word && '🍕').join(' ')} @@ -33,9 +34,6 @@ export default class PizzaTranslator extends Component { ); } } - -// skip this line if using Create React Native App -AppRegistry.registerComponent('AwesomeProject', () => PizzaTranslator); ``` In this example, we store `text` in the state, because it changes over time. diff --git a/website/versioned_docs/version-0.5/headless-js-android.md b/website/versioned_docs/version-0.5/headless-js-android.md index e26f0d6c3e5..7cfa4e67dba 100644 --- a/website/versioned_docs/version-0.5/headless-js-android.md +++ b/website/versioned_docs/version-0.5/headless-js-android.md @@ -67,8 +67,47 @@ service.putExtras(bundle); getApplicationContext().startService(service); ``` +## Retries + +By default, the headless JS task will not perform any retries. In order to do so, you need to create a `HeadlessJsRetryPolicy` and throw a specfic `Error`. + +`LinearCountingRetryPolicy` is an implementation of `HeadlessJsRetryPolicy` that allows you to specify a maximum number of retries with a fixed delay between each attempt. If that does not suit your needs then you can easily implement your own `HeadlessJsRetryPolicy`. These policies can simply be passed as an extra argument to the `HeadlessJsTaskConfig` constructor, e.g. + +```java +HeadlessJsRetryPolicy retryPolicy = new LinearCountingRetryPolicy( + 3, // Max number of retry attempts + 1000 // Delay between each retry attempt +); + +return new HeadlessJsTaskConfig( + 'SomeTaskName', + Arguments.fromBundle(extras), + 5000, + false, + retryPolicy +); +``` + +A retry attempt will only be made when a specific `Error` is thrown. Inside a headless JS task, you can import the error and throw it when a retry attempt is required. + +Example: + +```jsx +import {HeadlessJsTaskError} from 'HeadlessJsTask'; + +module.exports = async (taskData) => { + const condition = ...; + if (!condition) { + throw new HeadlessJsTaskError(); + } +}; +``` + +If you wish all errors to cause a retry attempt, you will need to catch them and throw the above error. + ## Caveats +- The function passed to `setTimeout` does not always behave as expected. Instead the function is called only when the application is launched again. If you just need to wait, use the retry functionality. - By default, your app will crash if you try to run a task while the app is in the foreground. This is to prevent developers from shooting themselves in the foot by doing a lot of work in a task and slowing the UI. You can pass a fourth `boolean` argument to control this behaviour. - If you start your service from a `BroadcastReceiver`, make sure to call `HeadlessJsTaskService.acquireWakeLockNow()` before returning from `onReceive()`. diff --git a/website/versioned_docs/version-0.5/height-and-width.md b/website/versioned_docs/version-0.5/height-and-width.md index 95a7b6f9fbb..e478ba61d9a 100644 --- a/website/versioned_docs/version-0.5/height-and-width.md +++ b/website/versioned_docs/version-0.5/height-and-width.md @@ -10,9 +10,9 @@ A component's height and width determine its size on the screen. The simplest way to set the dimensions of a component is by adding a fixed `width` and `height` to style. All dimensions in React Native are unitless, and represent density-independent pixels. -```SnackPlayer +```SnackPlayer name=Height%20and%20Width import React, { Component } from 'react'; -import { AppRegistry, View } from 'react-native'; +import { View } from 'react-native'; export default class FixedDimensionsBasics extends Component { render() { @@ -25,9 +25,6 @@ export default class FixedDimensionsBasics extends Component { ); } } - -// skip this line if using Create React Native App -AppRegistry.registerComponent('AwesomeProject', () => FixedDimensionsBasics); ``` Setting dimensions this way is common for components that should always render at exactly the same size, regardless of screen dimensions. @@ -38,9 +35,9 @@ Use `flex` in a component's style to have the component expand and shrink dynami > A component can only expand to fill available space if its parent has dimensions greater than 0. If a parent does not have either a fixed `width` and `height` or `flex`, the parent will have dimensions of 0 and the `flex` children will not be visible. -```SnackPlayer +````SnackPlayer name=Flex%20Dimensions import React, { Component } from 'react'; -import { AppRegistry, View } from 'react-native'; +import { View } from 'react-native'; export default class FlexDimensionsBasics extends Component { render() { @@ -56,9 +53,7 @@ export default class FlexDimensionsBasics extends Component { ); } } - -// skip this line if using Create React Native App -AppRegistry.registerComponent('AwesomeProject', () => FlexDimensionsBasics); ``` After you can control a component's size, the next step is to [learn how to lay it out on the screen](flexbox.md). +```` diff --git a/website/versioned_docs/version-0.5/images.md b/website/versioned_docs/version-0.5/images.md index 169d3d12e0d..b5644f98d29 100644 --- a/website/versioned_docs/version-0.5/images.md +++ b/website/versioned_docs/version-0.5/images.md @@ -68,7 +68,7 @@ Note that image sources required this way include size (width, height) info for The `require` syntax described above can be used to statically include audio, video or document files in your project as well. Most common file types are supported including `.mp3`, `.wav`, `.mp4`, `.mov`, `.html` and `.pdf`. See [packager defaults](https://github.com/facebook/metro/blob/master/packages/metro-config/src/defaults/defaults.js#L14-L44) for the full list. -You can add support for other types by creating a packager config file (see the [packager config file](https://github.com/facebook/react-native/blob/master/local-cli/util/Config.js#L68) for the full list of configuration options). +You can add support for other types by adding an [`assetExts` resolver option](https://facebook.github.io/metro/docs/en/configuration#assetexts) in your [Metro configuration](https://facebook.github.io/metro/docs/en/configuration). A caveat is that videos must use absolute positioning instead of `flexGrow`, since size info is not currently passed for non-image assets. This limitation doesn't occur for videos that are linked directly into Xcode or the Assets folder for Android. @@ -163,7 +163,7 @@ In some cases you might only want to display an image if it is already in the lo ## Local Filesystem Images -See [CameraRoll](cameraroll.md) for an example of using local resources that are outside of `Images.xcassets`. +See [CameraRoll](https://github.com/react-native-community/react-native-cameraroll) for an example of using local resources that are outside of `Images.xcassets`. ### Best Camera Roll Image diff --git a/website/versioned_docs/version-0.5/integration-with-existing-apps.md b/website/versioned_docs/version-0.5/integration-with-existing-apps.md index 6a9b8f00f38..6fbb390f945 100644 --- a/website/versioned_docs/version-0.5/integration-with-existing-apps.md +++ b/website/versioned_docs/version-0.5/integration-with-existing-apps.md @@ -9,7 +9,7 @@ React Native is great when you are starting a new mobile app from scratch. Howev The specific steps are different depending on what platform you're targeting.
    -
      +
        @@ -165,24 +165,30 @@ target 'NumberTileGame' do # Your 'node_modules' directory is probably in the root of your project, # but if not, adjust the `:path` accordingly - pod 'React', :path => '../node_modules/react-native', :subspecs => [ - 'Core', - 'CxxBridge', # Include this for RN >= 0.47 - 'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43 - 'RCTText', - 'RCTNetwork', - 'RCTWebSocket', # Needed for debugging - 'RCTAnimation', # Needed for FlatList and animations running on native UI thread - # Add any other subspecs you want to use in your project - ] - # Explicitly include Yoga if you are using RN >= 0.42.0 + pod 'React', :path => '../node_modules/react-native/' + pod 'React-Core', :path => '../node_modules/react-native/React' + pod 'React-DevSupport', :path => '../node_modules/react-native/React' + pod 'React-fishhook', :path => '../node_modules/react-native/Libraries/fishhook' + pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' + pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' + pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' + pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' + pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' + pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' + pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' + pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' + pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' + pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket' + + pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' + pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' + pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' + pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga' - # Third party deps podspec link pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' - end ``` diff --git a/website/versioned_docs/version-0.5/javascript-environment.md b/website/versioned_docs/version-0.5/javascript-environment.md index 23d21f67617..92dc226aad9 100644 --- a/website/versioned_docs/version-0.5/javascript-environment.md +++ b/website/versioned_docs/version-0.5/javascript-environment.md @@ -9,7 +9,7 @@ original_id: javascript-environment When using React Native, you're going to be running your JavaScript code in two environments: - In most cases, React Native will use [JavaScriptCore](http://trac.webkit.org/wiki/JavaScriptCore), the JavaScript engine that powers Safari. Note that on iOS, JavaScriptCore does not use JIT due to the absence of writable executable memory in iOS apps. -- When using Chrome debugging, all JavaScript code runs within Chrome itself, communicating with native code via WebSockets. Chrome uses [V8](https://code.google.com/p/v8/) as its JavaScript engine. +- When using Chrome debugging, all JavaScript code runs within Chrome itself, communicating with native code via WebSockets. Chrome uses [V8](https://v8.dev/) as its JavaScript engine. While both environments are very similar, you may end up hitting some inconsistencies. We're likely going to experiment with other JavaScript engines in the future, so it's best to avoid relying on specifics of any runtime. @@ -48,16 +48,16 @@ ES8 Stage 3 -- [Object Spread](https://github.com/sebmarkbage/ecmascript-rest-spread): `var extended = { ...obj, a: 10 };` - -Stage 1 - +- [Object Spread](https://github.com/tc39/proposal-object-rest-spread): `var extended = { ...obj, a: 10 };` +- [Static class fields](https://github.com/tc39/proposal-static-class-features): `class CustomDate { static epoch = new CustomDate(0); }` - [Optional Chaining](https://github.com/tc39/proposal-optional-chaining): `var name = obj.user?.name;` Specific - [JSX](https://reactjs.org/docs/jsx-in-depth.html): `` -- [Flow](http://flowtype.org/): `function foo(x: ?number): string {};` +- [Flow](https://flowtype.org/): `function foo(x: ?number): string {};` +- [TypeScript](https://flowtype.org/): `function foo(x: number | undefined): string {};` +- [Babel Template](https://babeljs.io/docs/en/babel-template): allows AST templating ## Polyfills @@ -69,7 +69,6 @@ Browser - [CommonJS require](https://nodejs.org/docs/latest/api/modules.html) - [XMLHttpRequest, fetch](network.md#content) - [{set, clear}{Timeout, Interval, Immediate}, {request, cancel}AnimationFrame](timers.md#content) -- [navigator.geolocation](geolocation.md#content) ES6 diff --git a/website/versioned_docs/version-0.5/more-resources.md b/website/versioned_docs/version-0.5/more-resources.md index 0f195877cf3..938c2c28ae3 100644 --- a/website/versioned_docs/version-0.5/more-resources.md +++ b/website/versioned_docs/version-0.5/more-resources.md @@ -16,7 +16,7 @@ If you're looking for a library that does a specific thing, check out [Awesome R ## Examples -Try out apps from the [Showcase](/react-native/showcase.html) to see what React Native is capable of! There are also some [example apps on GitHub](https://github.com/ReactNativeNews/React-Native-Apps). You can run the apps on a simulator or device, and you can see the source code for these apps, which is neat. +Try out apps from the [Showcase](/react-native/showcase/) to see what React Native is capable of! There are also some [example apps on GitHub](https://github.com/ReactNativeNews/React-Native-Apps). You can run the apps on a simulator or device, and you can see the source code for these apps, which is neat. The folks who built the app for Facebook's F8 conference also [open-sourced the code](https://github.com/fbsamples/f8app) and wrote up a [detailed series of tutorials](http://makeitopen.com/). This is useful if you want a more in-depth example that's more realistic than most sample apps out there. @@ -25,7 +25,7 @@ The folks who built the app for Facebook's F8 conference also [open-sourced the - Fellow developers write and publish React Native modules to npm and open source them on GitHub. - Making modules helps grow the React Native ecosystem and community. We recommend writing modules for your use cases and sharing them on npm. - Read the guides on Native Modules ([iOS](native-modules-ios.md), [Android](native-modules-android.md)) and Native UI Components ([iOS](native-components-ios.md), [Android](native-components-android.md)) if you are interested in extending native functionality. -- Looking for a pre-built component? Check [JS.coach](https://js.coach/react-native) or [Native Directory](https://native.directory/) to find what the community has been creating. +- Looking for a pre-built component? Check [JS.coach](https://js.coach/react-native) or [Native Directory](https://www.native.directory) to find what the community has been creating. ## Development Tools @@ -39,6 +39,6 @@ The folks who built the app for Facebook's F8 conference also [open-sourced the [Yoga](https://yogalayout.com/) is a stand-alone layout engine that extends beyond React Native and allows product engineers to build layouts quickly for multiple platforms with a highly optimized open source layout engine designed with speed, size, and ease of use in mind. -[Bugsnag](https://www.bugsnag.com/), [Microsoft App Center](https://appcenter.ms/), and [Sentry](https://sentry.io/welcome/) all provide excellent crash and error monitoring services for React and React Native apps. These services allow you to proactively monitor crashes and issues occuring on your apps in real time so you can fix them quickly and improve user experience. +[Bugsnag](https://www.bugsnag.com/), [Microsoft App Center](https://appcenter.ms/), and [Sentry](https://sentry.io/welcome/) all provide excellent crash and error monitoring services for React and React Native apps. These services allow you to proactively monitor crashes and issues occurring on your apps in real time so you can fix them quickly and improve user experience. The [React Developer Tools](debugging.md#react-developer-tools) are great for debugging React and React Native apps. diff --git a/website/versioned_docs/version-0.5/native-components-ios.md b/website/versioned_docs/version-0.5/native-components-ios.md index f55f5584bb6..15e3c60295b 100644 --- a/website/versioned_docs/version-0.5/native-components-ios.md +++ b/website/versioned_docs/version-0.5/native-components-ios.md @@ -383,6 +383,79 @@ class MyApp extends React.Component { } ``` +## Handling multiple native views + +A React Native view can have more than one child view in the view tree eg. + +```jsx + + + +
    - -
    - Target OS: - -
    - - - -

    Unsupported

    - -

    A Mac is required to build projects with native code for iOS. You can follow the Quick Start to learn how to build your app using Expo instead.

    - - - -

    Installing dependencies

    - -You will need Node, Watchman, the React Native command line interface, and Xcode. - -While you can use any editor of your choice to develop your app, you will need to install Xcode in order to set up the necessary tooling to build your React Native app for iOS. - - - -

    Installing dependencies

    - -You will need Node, Watchman, the React Native command line interface, a JDK, and Android Studio. - - - -

    Installing dependencies

    - -You will need Node, the React Native command line interface, a JDK, and Android Studio. - - - -

    Installing dependencies

    - -You will need Node, the React Native command line interface, Python2, a JDK, and Android Studio. - - - -While you can use any editor of your choice to develop your app, you will need to install Android Studio in order to set up the necessary tooling to build your React Native app for Android. - - - -

    Node, Watchman, JDK

    - -We recommend installing Node, Watchman, and JDK using [Homebrew](http://brew.sh/). Run the following commands in a Terminal after installing Homebrew: - -``` -brew install yarn -brew install node -brew install watchman -brew tap AdoptOpenJDK/openjdk -brew cask install adoptopenjdk8 -``` - -If you have already installed Node on your system, make sure it is Node 8.3 or newer. - -[Watchman](https://facebook.github.io/watchman) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance. - -If you have already installed JDK on your system, make sure it is JDK 8 or newer. - - - -

    Node

    - -Follow the [installation instructions for your Linux distribution](https://nodejs.org/en/download/package-manager/) to install Node 8.3 or newer. - - - -

    Node, Python2, JDK

    - -We recommend installing Node and Python2 via [Chocolatey](https://chocolatey.org), a popular package manager for Windows. - -React Native also requires a recent version of the [Java SE Development Kit (JDK)](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html), as well as Python 2. Both can be installed using Chocolatey. - -Open an Administrator Command Prompt (right click Command Prompt and select "Run as Administrator"), then run the following command: - -```powershell -choco install -y nodejs.install python2 jdk8 -``` - -If you have already installed Node on your system, make sure it is Node 8.3 or newer. If you already have a JDK on your system, make sure it is version 8 or newer. - -> You can find additional installation options on [Node's Downloads page](https://nodejs.org/en/download/). - - - -

    The React Native CLI

    - -Node comes with npm, which lets you install the React Native command line interface. - -Run the following command in a Terminal: - -``` -npm install -g react-native-cli -``` - -> If you get an error like `Cannot find module 'npmlog'`, try installing npm directly: `curl -0 -L https://npmjs.org/install.sh | sudo sh`. - - - -

    The React Native CLI

    - -Node comes with npm, which lets you install the React Native command line interface. - -Run the following command in a Command Prompt or shell: - -```powershell -npm install -g react-native-cli -``` - -> If you get an error like `Cannot find module 'npmlog'`, try installing npm directly: `curl -0 -L https://npmjs.org/install.sh | sudo sh`. - - - -

    Xcode

    - -The easiest way to install Xcode is via the [Mac App Store](https://itunes.apple.com/us/app/xcode/id497799835?mt=12). Installing Xcode will also install the iOS Simulator and all the necessary tools to build your iOS app. - -If you have already installed Xcode on your system, make sure it is version 9.4 or newer. - -

    Command Line Tools

    - -You will also need to install the Xcode Command Line Tools. Open Xcode, then choose "Preferences..." from the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown. - -![Xcode Command Line Tools](/react-native/docs/assets/GettingStartedXcodeCommandLineTools.png) - - - -

    Java Development Kit

    - -React Native requires version 8 of the Java SE Development Kit (JDK). You may download and install [OpenJDK](http://openjdk.java.net) from [AdoptOpenJDK](https://adoptopenjdk.net/) or your system packager. You may also [Download and install Oracle JDK 8](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html) if desired. - - - -

    Android development environment

    - -Setting up your development environment can be somewhat tedious if you're new to Android development. If you're already familiar with Android development, there are a few things you may need to configure. In either case, please make sure to carefully follow the next few steps. - - - -

    1. Install Android Studio

    - -[Download and install Android Studio](https://developer.android.com/studio/index.html). Choose a "Custom" setup when prompted to select an installation type. Make sure the boxes next to all of the following are checked: - - - -- `Android SDK` -- `Android SDK Platform` -- `Performance (Intel ® HAXM)` ([See here for AMD](https://android-developers.googleblog.com/2018/07/android-emulator-amd-processor-hyper-v.html)) -- `Android Virtual Device` - - - -- `Android SDK` -- `Android SDK Platform` -- `Android Virtual Device` - - - -Then, click "Next" to install all of these components. - -> If the checkboxes are grayed out, you will have a chance to install these components later on. - -Once setup has finalized and you're presented with the Welcome screen, proceed to the next step. - -

    2. Install the Android SDK

    - -Android Studio installs the latest Android SDK by default. Building a React Native app with native code, however, requires the `Android 9 (Pie)` SDK in particular. Additional Android SDKs can be installed through the SDK Manager in Android Studio. - -The SDK Manager can be accessed from the "Welcome to Android Studio" screen. Click on "Configure", then select "SDK Manager". - - - -![Android Studio Welcome](/react-native/docs/assets/GettingStartedAndroidStudioWelcomeMacOS.png) - - - -![Android Studio Welcome](/react-native/docs/assets/GettingStartedAndroidStudioWelcomeWindows.png) - - - -> The SDK Manager can also be found within the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. - -Select the "SDK Platforms" tab from within the SDK Manager, then check the box next to "Show Package Details" in the bottom right corner. Look for and expand the `Android 9 (Pie)` entry, then make sure the following items are checked: - -- `Android SDK Platform 28` -- `Intel x86 Atom_64 System Image` or `Google APIs Intel x86 Atom System Image` - -Next, select the "SDK Tools" tab and check the box next to "Show Package Details" here as well. Look for and expand the "Android SDK Build-Tools" entry, then make sure that `28.0.3` is selected. - -Finally, click "Apply" to download and install the Android SDK and related build tools. - -

    3. Configure the ANDROID_HOME environment variable

    - -The React Native tools require some environment variables to be set up in order to build apps with native code. - - - -Add the following lines to your `$HOME/.bash_profile` or `$HOME/.bashrc` config file: - - - -``` -export ANDROID_HOME=$HOME/Library/Android/sdk -export PATH=$PATH:$ANDROID_HOME/emulator -export PATH=$PATH:$ANDROID_HOME/tools -export PATH=$PATH:$ANDROID_HOME/tools/bin -export PATH=$PATH:$ANDROID_HOME/platform-tools -``` - - - -``` -export ANDROID_HOME=$HOME/Android/Sdk -export PATH=$PATH:$ANDROID_HOME/emulator -export PATH=$PATH:$ANDROID_HOME/tools -export PATH=$PATH:$ANDROID_HOME/tools/bin -export PATH=$PATH:$ANDROID_HOME/platform-tools -``` - - - -> `.bash_profile` is specific to `bash`. If you're using another shell, you will need to edit the appropriate shell-specific config file. - -Type `source $HOME/.bash_profile` to load the config into your current shell. Verify that ANDROID_HOME has been added to your path by running `echo $PATH`. - -> Please make sure you use the correct Android SDK path. You can find the actual location of the SDK in the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. - - - -Open the System pane under **System and Security** in the Windows Control Panel, then click on **Change settings...**. Open the **Advanced** tab and click on **Environment Variables...**. Click on **New...** to create a new `ANDROID_HOME` user variable that points to the path to your Android SDK: - -![ANDROID_HOME Environment Variable](/react-native/docs/assets/GettingStartedAndroidEnvironmentVariableANDROID_HOME.png) - -The SDK is installed, by default, at the following location: - -```powershell -c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk -``` - -You can find the actual location of the SDK in the Android Studio "Preferences" dialog, under **Appearance & Behavior** → **System Settings** → **Android SDK**. - -Open a new Command Prompt window to ensure the new environment variable is loaded before proceeding to the next step. - -

    4. Add platform-tools to Path

    - -Open the System pane under **System and Security** in the Windows Control Panel, then click on **Change settings...**. Open the **Advanced** tab and click on **Environment Variables...**. Select the **Path** variable, then click **Edit**. Click **New** and add the path to platform-tools to the list. - -The default location for this folder is: - -```powershell -c:\Users\YOUR_USERNAME\AppData\Local\Android\Sdk\platform-tools -``` - - - -

    Watchman

    - -Follow the [Watchman installation guide](https://facebook.github.io/watchman/docs/install.html#buildinstall) to compile and install Watchman from source. - -> [Watchman](https://facebook.github.io/watchman/docs/install.html) is a tool by Facebook for watching changes in the filesystem. It is highly recommended you install it for better performance and increased compatibility in certain edge cases (translation: you may be able to get by without installing this, but your mileage may vary; installing this now may save you from a headache later). - - - -

    Creating a new application

    - -Use the React Native command line interface to generate a new React Native project called "AwesomeProject": - -``` -react-native init AwesomeProject -``` - -This is not necessary if you are integrating React Native into an existing application, if you "ejected" from Expo (or Create React Native App), or if you're adding iOS support to an existing React Native project (see [Platform Specific Code](platform-specific-code.md)). You can also use a third-party CLI to init your React Native app, such as [Ignite CLI](https://github.com/infinitered/ignite). - -

    [Optional] Using a specific version

    - -If you want to start a new project with a specific React Native version, you can use the `--version` argument: - -``` -react-native init AwesomeProject --version X.XX.X -``` - -``` -react-native init AwesomeProject --version react-native@next -``` - - - -

    Creating a new application

    - -Use the React Native command line interface to generate a new React Native project called "AwesomeProject": - -``` -react-native init AwesomeProject -``` - -This is not necessary if you are integrating React Native into an existing application, if you "ejected" from Create React Native App, or if you're adding Android support to an existing React Native project (see [Platform Specific Code](platform-specific-code.md)). You can also use a third-party CLI to init your React Native app, such as [Ignite CLI](https://github.com/infinitered/ignite). - -

    [Optional] Using a specific version

    - -If you want to start a new project with a specific React Native version, you can use the `--version` argument: - -``` -react-native init AwesomeProject --version X.XX.X -``` - -``` -react-native init AwesomeProject --version react-native@next -``` - - - -

    Preparing the Android device

    - -You will need an Android device to run your React Native Android app. This can be either a physical Android device, or more commonly, you can use an Android Virtual Device which allows you to emulate an Android device on your computer. - -Either way, you will need to prepare the device to run Android apps for development. - -

    Using a physical device

    - -If you have a physical Android device, you can use it for development in place of an AVD by plugging it in to your computer using a USB cable and following the instructions [here](running-on-device.md). - -

    Using a virtual device

    - -If you use Android Studio to open `./AwesomeProject/android`, you can see the list of available Android Virtual Devices (AVDs) by opening the "AVD Manager" from within Android Studio. Look for an icon that looks like this: - -![Android Studio AVD Manager](/react-native/docs/assets/GettingStartedAndroidStudioAVD.png) - -If you have just installed Android Studio, you will likely need to [create a new AVD](https://developer.android.com/studio/run/managing-avds.html). Select "Create Virtual Device...", then pick any Phone from the list and click "Next", then select the **Pie** API Level 28 image. - - - -> We recommend configuring [VM acceleration](https://developer.android.com/studio/run/emulator-acceleration.html#vm-linux) on your system to improve performance. Once you've followed those instructions, go back to the AVD Manager. - - - -> If you don't have HAXM installed, click on "Install HAXM" or follow [these instructions](https://github.com/intel/haxm/wiki/Installation-Instructions-on-Windows) to set it up, then go back to the AVD Manager. - - - -> If you don't have HAXM installed, follow [these instructions](https://github.com/intel/haxm/wiki/Installation-Instructions-on-macOS) to set it up, then go back to the AVD Manager. - - - -Click "Next" then "Finish" to create your AVD. At this point you should be able to click on the green triangle button next to your AVD to launch it, then proceed to the next step. - - - -

    Running your React Native application

    - -Run `react-native run-ios` inside your React Native project folder: - -``` -cd AwesomeProject -react-native run-ios -``` - -You should see your new app running in the iOS Simulator shortly. - -![AwesomeProject on iOS](/react-native/docs/assets/GettingStartediOSSuccess.png) - -`react-native run-ios` is just one way to run your app. You can also run it directly from within Xcode. - -> If you can't get this to work, see the [Troubleshooting](troubleshooting.md#content) page. - -

    Running on a device

    - -The above command will automatically run your app on the iOS Simulator by default. If you want to run the app on an actual physical iOS device, please follow the instructions [here](running-on-device.md). - - - -

    Running your React Native application

    - -Run `react-native run-android` inside your React Native project folder: - -``` -cd AwesomeProject -react-native run-android -``` - -If everything is set up correctly, you should see your new app running in your Android emulator shortly. - - - -![AwesomeProject on Android](/react-native/docs/assets/GettingStartedAndroidSuccessMacOS.png) - - - -![AwesomeProject on Android](/react-native/docs/assets/GettingStartedAndroidSuccessWindows.png) - - - -`react-native run-android` is just one way to run your app - you can also run it directly from within Android Studio. - -> If you can't get this to work, see the [Troubleshooting](troubleshooting.md#content) page. - - - -

    Modifying your app

    - -Now that you have successfully run the app, let's modify it. - - - -- Open `App.js` in your text editor of choice and edit some lines. -- Hit `⌘R` in your iOS Simulator to reload the app and see your changes! - - - -- Open `App.js` in your text editor of choice and edit some lines. -- Press the `R` key twice or select `Reload` from the Developer Menu (`⌘M`) to see your changes! - - - -

    Modifying your app

    - -Now that you have successfully run the app, let's modify it. - -- Open `App.js` in your text editor of choice and edit some lines. -- Press the `R` key twice or select `Reload` from the Developer Menu (`Ctrl + M`) to see your changes! - - - -

    That's it!

    - -Congratulations! You've successfully run and modified your first React Native app. - -
    - - - -

    That's it!

    - -Congratulations! You've successfully run and modified your first React Native app. - -
    - - - -

    Now what?

    - -- Turn on [Live Reload](debugging.md#reloading-javascript) in the Developer Menu. Your app will now reload automatically whenever you save any changes! - -- If you want to add this new React Native code to an existing application, check out the [Integration guide](integration-with-existing-apps.md). - -If you're curious to learn more about React Native, continue on to the [Tutorial](tutorial.md). - - - -

    Now what?

    - -- Turn on [Live Reload](debugging.md#reloading-javascript) in the Developer Menu. Your app will now reload automatically whenever you save any changes! - -- If you want to add this new React Native code to an existing application, check out the [Integration guide](integration-with-existing-apps.md). - -If you're curious to learn more about React Native, continue on to the [Tutorial](tutorial.md). diff --git a/website/versioned_docs/version-0.60/handling-text-input.md b/website/versioned_docs/version-0.60/handling-text-input.md deleted file mode 100644 index 3790f2d002e..00000000000 --- a/website/versioned_docs/version-0.60/handling-text-input.md +++ /dev/null @@ -1,43 +0,0 @@ ---- -id: version-0.60-handling-text-input -title: Handling Text Input -original_id: handling-text-input ---- - -[`TextInput`](textinput.md#content) is a basic component that allows the user to enter text. It has an `onChangeText` prop that takes a function to be called every time the text changed, and an `onSubmitEditing` prop that takes a function to be called when the text is submitted. - -For example, let's say that as the user types, you're translating their words into a different language. In this new language, every single word is written the same way: 🍕. So the sentence "Hello there Bob" would be translated as "🍕🍕🍕". - -```SnackPlayer name=Handling%20Text%20Input -import React, { Component } from 'react'; -import { Text, TextInput, View } from 'react-native'; - -export default class PizzaTranslator extends Component { - constructor(props) { - super(props); - this.state = {text: ''}; - } - - render() { - return ( - - this.setState({text})} - value={this.state.text} - /> - - {this.state.text.split(' ').map((word) => word && '🍕').join(' ')} - - - ); - } -} -``` - -In this example, we store `text` in the state, because it changes over time. - -There are a lot more things you might want to do with a text input. For example, you could validate the text inside while the user types. For more detailed examples, see the [React docs on controlled components](https://reactjs.org/docs/forms.html#controlled-components), or the [reference docs for TextInput](textinput.md). - -Text input is one of the ways the user interacts with the app. Next, let's look at another type of input and [learn how to handle touches](handling-touches.md). diff --git a/website/versioned_docs/version-0.60/headless-js-android.md b/website/versioned_docs/version-0.60/headless-js-android.md deleted file mode 100644 index 66b5abf1081..00000000000 --- a/website/versioned_docs/version-0.60/headless-js-android.md +++ /dev/null @@ -1,185 +0,0 @@ ---- -id: version-0.60-headless-js-android -title: Headless JS -original_id: headless-js-android ---- - -Headless JS is a way to run tasks in JavaScript while your app is in the background. It can be used, for example, to sync fresh data, handle push notifications, or play music. - -## The JS API - -A task is a simple async function that you register on `AppRegistry`, similar to registering React applications: - -```jsx -AppRegistry.registerHeadlessTask('SomeTaskName', () => require('SomeTaskName')); -``` - -Then, in `SomeTaskName.js`: - -```jsx -module.exports = async (taskData) => { - // do stuff -}; -``` - -You can do anything in your task such as network requests, timers and so on, as long as it doesn't touch UI. Once your task completes (i.e. the promise is resolved), React Native will go into "paused" mode (unless there are other tasks running, or there is a foreground app). - -## The Java API - -Yes, this does still require some native code, but it's pretty thin. You need to extend `HeadlessJsTaskService` and override `getTaskConfig`, e.g.: - -```java -public class MyTaskService extends HeadlessJsTaskService { - - @Override - protected @Nullable HeadlessJsTaskConfig getTaskConfig(Intent intent) { - Bundle extras = intent.getExtras(); - if (extras != null) { - return new HeadlessJsTaskConfig( - "SomeTaskName", - Arguments.fromBundle(extras), - 5000, // timeout for the task - false // optional: defines whether or not the task is allowed in foreground. Default is false - ); - } - return null; - } -} -``` - -Then add the service to your `AndroidManifest.xml` file: - -``` - -``` - -Now, whenever you [start your service][0], e.g. as a periodic task or in response to some system event / broadcast, JS will spin up, run your task, then spin down. - -Example: - -```java -Intent service = new Intent(getApplicationContext(), MyTaskService.class); -Bundle bundle = new Bundle(); - -bundle.putString("foo", "bar"); -service.putExtras(bundle); - -getApplicationContext().startService(service); -``` - -## Retries - -By default, the headless JS task will not perform any retries. In order to do so, you need to create a `HeadlessJsRetryPolicy` and throw a specfic `Error`. - -`LinearCountingRetryPolicy` is an implementation of `HeadlessJsRetryPolicy` that allows you to specify a maximum number of retries with a fixed delay between each attempt. If that does not suit your needs then you can easily implement your own `HeadlessJsRetryPolicy`. These policies can simply be passed as an extra argument to the `HeadlessJsTaskConfig` constructor, e.g. - -```java -HeadlessJsRetryPolicy retryPolicy = new LinearCountingRetryPolicy( - 3, // Max number of retry attempts - 1000 // Delay between each retry attempt -); - -return new HeadlessJsTaskConfig( - 'SomeTaskName', - Arguments.fromBundle(extras), - 5000, - false, - retryPolicy -); -``` - -A retry attempt will only be made when a specific `Error` is thrown. Inside a headless JS task, you can import the error and throw it when a retry attempt is required. - -Example: - -```jsx -import {HeadlessJsTaskError} from 'HeadlessJsTask'; - -module.exports = async (taskData) => { - const condition = ...; - if (!condition) { - throw new HeadlessJsTaskError(); - } -}; -``` - -If you wish all errors to cause a retry attempt, you will need to catch them and throw the above error. - -## Caveats - -- The function passed to `setTimeout` does not always behave as expected. Instead the function is called only when the application is launched again. If you just need to wait, use the retry functionality. -- By default, your app will crash if you try to run a task while the app is in the foreground. This is to prevent developers from shooting themselves in the foot by doing a lot of work in a task and slowing the UI. You can pass a fourth `boolean` argument to control this behaviour. -- If you start your service from a `BroadcastReceiver`, make sure to call `HeadlessJsTaskService.acquireWakeLockNow()` before returning from `onReceive()`. - -## Example Usage - -Service can be started from Java API. First you need to decide when the service should be started and implement your solution accordingly. Here is a simple example that reacts to network connection change. - -Following lines shows part of Android manifest file for registering broadcast receiver. - -```xml - - - - - -``` - -Broadcast receiver then handles intent that was broadcasted in onReceive function. This is a great place to check whether your app is on foreground or not. If app is not on foreground we can prepare our intent to be started, with no information or additional information bundled using `putExtra` (keep in mind bundle can handle only parcelable values). In the end service is started and wakelock is acquired. - -```java -public class NetworkChangeReceiver extends BroadcastReceiver { - - @Override - public void onReceive(final Context context, final Intent intent) { - /** - This part will be called everytime network connection is changed - e.g. Connected -> Not Connected - **/ - if (!isAppOnForeground((context))) { - /** - We will start our service and send extra info about - network connections - **/ - boolean hasInternet = isNetworkAvailable(context); - Intent serviceIntent = new Intent(context, MyTaskService.class); - serviceIntent.putExtra("hasInternet", hasInternet); - context.startService(serviceIntent); - HeadlessJsTaskService.acquireWakeLockNow(context); - } - } - - private boolean isAppOnForeground(Context context) { - /** - We need to check if app is in foreground otherwise the app will crash. - http://stackoverflow.com/questions/8489993/check-android-application-is-in-foreground-or-not - **/ - ActivityManager activityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE); - List appProcesses = - activityManager.getRunningAppProcesses(); - if (appProcesses == null) { - return false; - } - final String packageName = context.getPackageName(); - for (ActivityManager.RunningAppProcessInfo appProcess : appProcesses) { - if (appProcess.importance == - ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && - appProcess.processName.equals(packageName)) { - return true; - } - } - return false; - } - - public static boolean isNetworkAvailable(Context context) { - ConnectivityManager cm = (ConnectivityManager) - context.getSystemService(Context.CONNECTIVITY_SERVICE); - NetworkInfo netInfo = cm.getActiveNetworkInfo(); - return (netInfo != null && netInfo.isConnected()); - } - - -} -``` - -[0]: https://developer.android.com/reference/android/content/Context.html#startService(android.content.Intent) diff --git a/website/versioned_docs/version-0.60/height-and-width.md b/website/versioned_docs/version-0.60/height-and-width.md deleted file mode 100644 index ed0f86dc8c6..00000000000 --- a/website/versioned_docs/version-0.60/height-and-width.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -id: version-0.60-height-and-width -title: Height and Width -original_id: height-and-width ---- - -A component's height and width determine its size on the screen. - -## Fixed Dimensions - -The simplest way to set the dimensions of a component is by adding a fixed `width` and `height` to style. All dimensions in React Native are unitless, and represent density-independent pixels. - -```SnackPlayer name=Height%20and%20Width -import React, { Component } from 'react'; -import { View } from 'react-native'; - -export default class FixedDimensionsBasics extends Component { - render() { - return ( - - - - - - ); - } -} -``` - -Setting dimensions this way is common for components that should always render at exactly the same size, regardless of screen dimensions. - -## Flex Dimensions - -Use `flex` in a component's style to have the component expand and shrink dynamically based on available space. Normally you will use `flex: 1`, which tells a component to fill all available space, shared evenly amongst other components with the same parent. The larger the `flex` given, the higher the ratio of space a component will take compared to its siblings. - -> A component can only expand to fill available space if its parent has dimensions greater than 0. If a parent does not have either a fixed `width` and `height` or `flex`, the parent will have dimensions of 0 and the `flex` children will not be visible. - -````SnackPlayer name=Flex%20Dimensions -import React, { Component } from 'react'; -import { View } from 'react-native'; - -export default class FlexDimensionsBasics extends Component { - render() { - return ( - // Try removing the `flex: 1` on the parent View. - // The parent will not have dimensions, so the children can't expand. - // What if you add `height: 300` instead of `flex: 1`? - - - - - - ); - } -} -``` - -After you can control a component's size, the next step is to [learn how to lay it out on the screen](flexbox.md). -```` diff --git a/website/versioned_docs/version-0.60/images.md b/website/versioned_docs/version-0.60/images.md deleted file mode 100644 index 5392c803970..00000000000 --- a/website/versioned_docs/version-0.60/images.md +++ /dev/null @@ -1,223 +0,0 @@ ---- -id: version-0.60-images -title: Images -original_id: images ---- - -## Static Image Resources - -React Native provides a unified way of managing images and other media assets 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: - -```jsx - -``` - -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 correct file for the platform. - -You can also use the `@2x` and `@3x` suffixes to provide images for different screen densities. If you have the following file structure: - -``` -. -├── button.js -└── img - ├── check.png - ├── check@2x.png - └── check@3x.png -``` - -...and `button.js` code contains: - -```jsx - -``` - -...the packager will bundle and serve the image corresponding to device's screen density. For example, `check@2x.png`, will be used on an iPhone 7, while`check@3x.png` will be used on an iPhone 7 Plus or a Nexus 5. If there is no image matching the screen density, the closest best option will be selected. - -On Windows, you might need to restart the packager if you add new images to your project. - -Here are some benefits that you get: - -1. Same system on iOS and Android. -2. Images live in the same folder as your JavaScript code. Components are self-contained. -3. No global namespace, i.e. you don't have to worry about name collisions. -4. Only the images that are actually used will be packaged into your app. -5. Adding and changing images doesn't require app recompilation, just refresh the simulator as you normally do. -6. The packager knows the image dimensions, no need to duplicate it in the code. -7. Images can be distributed via [npm](https://www.npmjs.com/) packages. - -In order for this to work, the image name in `require` has to be known statically. - -```jsx -// GOOD -; - -// BAD -var icon = this.props.active ? 'my-icon-active' : 'my-icon-inactive'; -; - -// GOOD -var icon = this.props.active - ? require('./my-icon-active.png') - : require('./my-icon-inactive.png'); -; -``` - -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. - -## Static Non-Image Resources - -The `require` syntax described above can be used to statically include audio, video or document files in your project as well. Most common file types are supported including `.mp3`, `.wav`, `.mp4`, `.mov`, `.html` and `.pdf`. See [packager defaults](https://github.com/facebook/metro/blob/master/packages/metro-config/src/defaults/defaults.js#L14-L44) for the full list. - -You can add support for other types by adding an [`assetExts` resolver option](https://facebook.github.io/metro/docs/en/configuration#assetexts) in your [Metro configuration](https://facebook.github.io/metro/docs/en/configuration). - -A caveat is that videos must use absolute positioning instead of `flexGrow`, since size info is not currently passed for non-image assets. This limitation doesn't occur for videos that are linked directly into Xcode or the Assets folder for Android. - -## Images From Hybrid App's Resources - -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. - -For images included via Xcode asset catalogs or in the Android drawable folder, use the image name without the extension: - -```jsx - -``` - -For images in the Android assets folder, use the `asset:/` scheme: - -```jsx - -``` - -These approaches provide 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. - -## Network Images - -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_. It's highly recommended that you use https as well in order to satisfy [App Transport Security](running-on-device.md#app-transport-security) requirements on iOS. - -```jsx -// GOOD - - -// BAD - -``` - -### Network Requests for Images - -If you would like to set such things as the HTTP-Verb, Headers or a Body along with the image request, you may do this by defining these properties on the source object: - -```jsx - -``` - -## Uri Data Images - -Sometimes, you might be getting encoded image data from a REST API call. You can use the `'data:'` uri scheme to use these images. Same as for network resources, _you will need to manually specify the dimensions of your image_. - -> This is recommended for very small and dynamic images only, like icons in a list from a DB. - -```jsx -// include at least width and height! - -``` - -### Cache Control (iOS Only) - -In some cases you might only want to display an image if it is already in the local cache, i.e. a low resolution placeholder until a higher resolution is available. In other cases you do not care if the image is outdated and are willing to display an outdated image to save bandwidth. The `cache` source property gives you control over how the network layer interacts with the cache. - -- `default`: Use the native platforms default strategy. -- `reload`: The data for the URL will be loaded from the originating source. No existing cache data should be used to satisfy a URL load request. -- `force-cache`: The existing cached data will be used to satisfy the request, regardless of its age or expiration date. If there is no existing data in the cache corresponding the request, the data is loaded from the originating source. -- `only-if-cached`: The existing cache data will be used to satisfy a request, regardless of its age or expiration date. If there is no existing data in the cache corresponding to a URL load request, no attempt is made to load the data from the originating source, and the load is considered to have failed. - -```jsx - -``` - -## Local Filesystem Images - -See [CameraRoll](https://github.com/react-native-community/react-native-cameraroll) for an example of using local resources that are outside of `Images.xcassets`. - -### Best Camera Roll Image - -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. - -## Why Not Automatically Size Everything? - -_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: - -```jsx -{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573} -``` - -## Source as an object - -In React Native, one interesting decision is that the `src` attribute is named `source` and doesn't take a string but an object with a `uri` attribute. - -```jsx - -``` - -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. - -## Background Image via Nesting - -A common feature request from developers familiar with the web is `background-image`. To handle this use case, you can use the `` component, which has the same props as ``, and add whatever children to it you would like to layer on top of it. - -You might not want to use `` in some cases, since the implementation is very simple. Refer to ``'s [documentation](imagebackground.md) for more insight, and create your own custom component when needed. - -```jsx -return ( - - Inside - -); -``` - -Note that you must specify some width and height style attributes. - -## iOS Border Radius Styles - -Please note that the following corner specific, border radius style properties are currently ignored by iOS's image component: - -- `borderTopLeftRadius` -- `borderTopRightRadius` -- `borderBottomLeftRadius` -- `borderBottomRightRadius` - -## Off-thread Decoding - -Image decoding can take more than a frame-worth of time. This is one of the major sources 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. diff --git a/website/versioned_docs/version-0.60/integration-with-existing-apps.md b/website/versioned_docs/version-0.60/integration-with-existing-apps.md deleted file mode 100644 index 75e1345a4de..00000000000 --- a/website/versioned_docs/version-0.60/integration-with-existing-apps.md +++ /dev/null @@ -1,799 +0,0 @@ ---- -id: version-0.60-integration-with-existing-apps -title: Integration with Existing Apps -original_id: integration-with-existing-apps ---- - -React Native is great when you are starting a new mobile app from scratch. However, it also works well for adding a single view or user flow to existing native applications. With a few steps, you can add new React Native based features, screens, views, etc. - -The specific steps are different depending on what platform you're targeting. - -
    -
      - - - -
    -
    - - - -## Key Concepts - - - -The keys to integrating React Native components into your iOS application are to: - -1. Set up React Native dependencies and directory structure. -2. Understand what React Native components you will use in your app. -3. Add these components as dependencies using CocoaPods. -4. Develop your React Native components in JavaScript. -5. Add a `RCTRootView` to your iOS app. This view will serve as the container for your React Native component. -6. Start the React Native server and run your native application. -7. Verify that the React Native aspect of your application works as expected. - - - -The keys to integrating React Native components into your Android application are to: - -1. Set up React Native dependencies and directory structure. -2. Develop your React Native components in JavaScript. -3. Add a `ReactRootView` to your Android app. This view will serve as the container for your React Native component. -4. Start the React Native server and run your native application. -5. Verify that the React Native aspect of your application works as expected. - - - -## Prerequisites - - - -Follow the instructions for building apps with native code from the [Getting Started guide](getting-started.md) to configure your development environment for building React Native apps for iOS. - -### 1. Set up directory structure - -To ensure a smooth experience, create a new folder for your integrated React Native project, then copy your existing iOS project to a `/ios` subfolder. - - - -Follow the instructions for building apps with native code from the [Getting Started guide](getting-started.md) to configure your development environment for building React Native apps for Android. - -### 1. Set up directory structure - -To ensure a smooth experience, create a new folder for your integrated React Native project, then copy your existing Android project to an `/android` subfolder. - - - -### 2. Install JavaScript dependencies - -Go to the root directory for your project and create a new `package.json` file with the following contents: - -``` -{ - "name": "MyReactNativeApp", - "version": "0.0.1", - "private": true, - "scripts": { - "start": "yarn react-native start" - } -} -``` - -Next, make sure you have [installed the yarn package manager](https://yarnpkg.com/lang/en/docs/install/). - -Install the `react` and `react-native` packages. Open a terminal or command prompt, then navigate to the directory with your `package.json` file and run: - -``` -$ yarn add react-native -``` - -This will print a message similar to the following (scroll up in the yarn output to see it): - -> warning "react-native@0.52.2" has unmet peer dependency "react@16.2.0". - -This is OK, it means we also need to install React: - -``` -$ yarn add react@version_printed_above -``` - -Yarn has created a new `/node_modules` folder. This folder stores all the JavaScript dependencies required to build your project. - -Add `node_modules/` to your `.gitignore` file. - - - -### 3. Install CocoaPods - -[CocoaPods](http://cocoapods.org) is a package management tool for iOS and macOS development. We use it to add the actual React Native framework code locally into your current project. - -We recommend installing CocoaPods using [Homebrew](http://brew.sh/). - -``` -$ brew install cocoapods -``` - -> It is technically possible not to use CocoaPods, but that would require manual library and linker additions that would overly complicate this process. - - - -## Adding React Native to your app - - - -Assume the [app for integration](https://github.com/JoelMarcey/iOS-2048) is a [2048](https://en.wikipedia.org/wiki/2048_%28video_game%29) game. Here is what the main menu of the native application looks like without React Native. - - - -Assume the [app for integration](https://github.com/JoelMarcey/swift-2048) is a [2048](https://en.wikipedia.org/wiki/2048_%28video_game%29) game. Here is what the main menu of the native application looks like without React Native. - - - -![Before RN Integration](/react-native/docs/assets/react-native-existing-app-integration-ios-before.png) - -### Command Line Tools for Xcode - -Install the Command Line Tools. Choose "Preferences..." in the Xcode menu. Go to the Locations panel and install the tools by selecting the most recent version in the Command Line Tools dropdown. - -![Xcode Command Line Tools](/react-native/docs/assets/GettingStartedXcodeCommandLineTools.png) - -### Configuring CocoaPods dependencies - -Before you integrate React Native into your application, you will want to decide what parts of the React Native framework you would like to integrate. We will use CocoaPods to specify which of these "subspecs" your app will depend on. - -The list of supported `subspec`s is available in [`/node_modules/react-native/React.podspec`](https://github.com/facebook/react-native/blob/master/React.podspec). They are generally named by functionality. For example, you will generally always want the `Core` `subspec`. That will get you the `AppRegistry`, `StyleSheet`, `View` and other core React Native libraries. If you want to add the React Native `Text` library (e.g., for `` elements), then you will need the `RCTText` `subspec`. If you want the `Image` library (e.g., for `` elements), then you will need the `RCTImage` `subspec`. - -You can specify which `subspec`s your app will depend on in a `Podfile` file. The easiest way to create a `Podfile` is by running the CocoaPods `init` command in the `/ios` subfolder of your project: - -``` -$ pod init -``` - -The `Podfile` will contain a boilerplate setup that you will tweak for your integration purposes. In the end, `Podfile` should look something similar to this: - - - -``` -# The target name is most likely the name of your project. -target 'NumberTileGame' do - - # Your 'node_modules' directory is probably in the root of your project, - # but if not, adjust the `:path` accordingly - pod 'React', :path => '../node_modules/react-native/' - pod 'React-Core', :path => '../node_modules/react-native/React' - pod 'React-DevSupport', :path => '../node_modules/react-native/React' - pod 'React-fishhook', :path => '../node_modules/react-native/Libraries/fishhook' - pod 'React-RCTActionSheet', :path => '../node_modules/react-native/Libraries/ActionSheetIOS' - pod 'React-RCTAnimation', :path => '../node_modules/react-native/Libraries/NativeAnimation' - pod 'React-RCTBlob', :path => '../node_modules/react-native/Libraries/Blob' - pod 'React-RCTImage', :path => '../node_modules/react-native/Libraries/Image' - pod 'React-RCTLinking', :path => '../node_modules/react-native/Libraries/LinkingIOS' - pod 'React-RCTNetwork', :path => '../node_modules/react-native/Libraries/Network' - pod 'React-RCTSettings', :path => '../node_modules/react-native/Libraries/Settings' - pod 'React-RCTText', :path => '../node_modules/react-native/Libraries/Text' - pod 'React-RCTVibration', :path => '../node_modules/react-native/Libraries/Vibration' - pod 'React-RCTWebSocket', :path => '../node_modules/react-native/Libraries/WebSocket' - - pod 'React-cxxreact', :path => '../node_modules/react-native/ReactCommon/cxxreact' - pod 'React-jsi', :path => '../node_modules/react-native/ReactCommon/jsi' - pod 'React-jsiexecutor', :path => '../node_modules/react-native/ReactCommon/jsiexecutor' - pod 'React-jsinspector', :path => '../node_modules/react-native/ReactCommon/jsinspector' - pod 'yoga', :path => '../node_modules/react-native/ReactCommon/yoga' - - pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' - pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' - pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' -end -``` - - - -``` -source 'https://github.com/CocoaPods/Specs.git' - -# Required for Swift apps -platform :ios, '8.0' -use_frameworks! - -# The target name is most likely the name of your project. -target 'swift-2048' do - - # Your 'node_modules' directory is probably in the root of your project, - # but if not, adjust the `:path` accordingly - pod 'React', :path => '../node_modules/react-native', :subspecs => [ - 'Core', - 'CxxBridge', # Include this for RN >= 0.47 - 'DevSupport', # Include this to enable In-App Devmenu if RN >= 0.43 - 'RCTText', - 'RCTNetwork', - 'RCTWebSocket', # needed for debugging - # Add any other subspecs you want to use in your project - ] - # Explicitly include Yoga if you are using RN >= 0.42.0 - pod "yoga", :path => "../node_modules/react-native/ReactCommon/yoga" - - # Third party deps podspec link - pod 'DoubleConversion', :podspec => '../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec' - pod 'glog', :podspec => '../node_modules/react-native/third-party-podspecs/glog.podspec' - pod 'Folly', :podspec => '../node_modules/react-native/third-party-podspecs/Folly.podspec' - -end -``` - - - -After you have created your `Podfile`, you are ready to install the React Native pod. - -``` -$ pod install -``` - -You should see output such as: - -``` -Analyzing dependencies -Fetching podspec for `React` from `../node_modules/react-native` -Downloading dependencies -Installing React (0.26.0) -Generating Pods project -Integrating client project -Sending stats -Pod installation complete! There are 3 dependencies from the Podfile and 1 total pod installed. -``` - -> If this fails with errors mentioning `xcrun`, make sure that in Xcode in Preferences > Locations the Command Line Tools are assigned. - - - -> If you get a warning such as "_The `swift-2048 [Debug]` target overrides the `FRAMEWORK_SEARCH_PATHS` build setting defined in `Pods/Target Support Files/Pods-swift-2048/Pods-swift-2048.debug.xcconfig`. This can lead to problems with the CocoaPods installation_", then make sure the `Framework Search Paths` in `Build Settings` for both `Debug` and `Release` only contain `$(inherited)`. - - - -### Code integration - -Now we will actually modify the native iOS application to integrate React Native. For our 2048 sample app, we will add a "High Score" screen in React Native. - -#### The React Native component - -The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application. - -##### 1. Create a `index.js` file - -First, create an empty `index.js` file in the root of your React Native project. - -`index.js` is the starting point for React Native applications, and it is always required. It can be a small file that `require`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will just put everything in `index.js`. - -##### 2. Add your React Native code - -In your `index.js`, create your component. In our sample here, we will add simple `` component within a styled `` - -```jsx -import React from 'react'; -import {AppRegistry, StyleSheet, Text, View} from 'react-native'; - -class RNHighScores extends React.Component { - render() { - var contents = this.props['scores'].map((score) => ( - - {score.name}:{score.value} - {'\n'} - - )); - return ( - - 2048 High Scores! - {contents} - - ); - } -} - -const styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - alignItems: 'center', - backgroundColor: '#FFFFFF', - }, - highScoresTitle: { - fontSize: 20, - textAlign: 'center', - margin: 10, - }, - scores: { - textAlign: 'center', - color: '#333333', - marginBottom: 5, - }, -}); - -// Module name -AppRegistry.registerComponent('RNHighScores', () => RNHighScores); -``` - -> `RNHighScores` is the name of your module that will be used when you add a view to React Native from within your iOS application. - -#### The Magic: `RCTRootView` - -Now that your React Native component is created via `index.js`, you need to add that component to a new or existing `ViewController`. The easiest path to take is to optionally create an event path to your component and then add that component to an existing `ViewController`. - -We will tie our React Native component with a new native view in the `ViewController` that will actually host it called `RCTRootView` . - -##### 1. Create an Event Path - -You can add a new link on the main game menu to go to the "High Score" React Native page. - -![Event Path](/react-native/docs/assets/react-native-add-react-native-integration-link.png) - -##### 2. Event Handler - -We will now add an event handler from the menu link. A method will be added to the main `ViewController` of your application. This is where `RCTRootView` comes into play. - -When you build a React Native application, you use the React Native packager to create an `index.bundle` that will be served by the React Native server. Inside `index.bundle` will be our `RNHighScore` module. So, we need to point our `RCTRootView` to the location of the `index.bundle` resource (via `NSURL`) and tie it to the module. - -We will, for debugging purposes, log that the event handler was invoked. Then, we will create a string with the location of our React Native code that exists inside the `index.bundle`. Finally, we will create the main `RCTRootView`. Notice how we provide `RNHighScores` as the `moduleName` that we created [above](#the-react-native-component) when writing the code for our React Native component. - - - -First `import` the `RCTRootView` header. - -```objectivec -#import -``` - -> The `initialProperties` are here for illustration purposes so we have some data for our high score screen. In our React Native component, we will use `this.props` to get access to that data. - -```objectivec -- (IBAction)highScoreButtonPressed:(id)sender { - NSLog(@"High Score Button Pressed"); - NSURL *jsCodeLocation = [NSURL URLWithString:@"http://localhost:8081/index.bundle?platform=ios"]; - - RCTRootView *rootView = - [[RCTRootView alloc] initWithBundleURL: jsCodeLocation - moduleName: @"RNHighScores" - initialProperties: - @{ - @"scores" : @[ - @{ - @"name" : @"Alex", - @"value": @"42" - }, - @{ - @"name" : @"Joel", - @"value": @"10" - } - ] - } - launchOptions: nil]; - UIViewController *vc = [[UIViewController alloc] init]; - vc.view = rootView; - [self presentViewController:vc animated:YES completion:nil]; -} -``` - -> Note that `RCTRootView initWithURL` starts up a new JSC VM. To save resources and simplify the communication between RN views in different parts of your native app, you can have multiple views powered by React Native that are associated with a single JS runtime. To do that, instead of using `[RCTRootView alloc] initWithURL`, use [`RCTBridge initWithBundleURL`](https://github.com/facebook/react-native/blob/master/React/Base/RCTBridge.h#L93) to create a bridge and then use `RCTRootView initWithBridge`. - - - -First `import` the `React` library. - -```jsx -import React -``` - -> The `initialProperties` are here for illustration purposes so we have some data for our high score screen. In our React Native component, we will use `this.props` to get access to that data. - -```swift -@IBAction func highScoreButtonTapped(sender : UIButton) { - NSLog("Hello") - let jsCodeLocation = URL(string: "http://localhost:8081/index.bundle?platform=ios") - let mockData:NSDictionary = ["scores": - [ - ["name":"Alex", "value":"42"], - ["name":"Joel", "value":"10"] - ] - ] - - let rootView = RCTRootView( - bundleURL: jsCodeLocation, - moduleName: "RNHighScores", - initialProperties: mockData as [NSObject : AnyObject], - launchOptions: nil - ) - let vc = UIViewController() - vc.view = rootView - self.present(vc, animated: true, completion: nil) -} -``` - -> Note that `RCTRootView bundleURL` starts up a new JSC VM. To save resources and simplify the communication between RN views in different parts of your native app, you can have multiple views powered by React Native that are associated with a single JS runtime. To do that, instead of using `RCTRootView bundleURL`, use [`RCTBridge initWithBundleURL`](https://github.com/facebook/react-native/blob/master/React/Base/RCTBridge.h#L89) to create a bridge and then use `RCTRootView initWithBridge`. - - - -> When moving your app to production, the `NSURL` can point to a pre-bundled file on disk via something like `[[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];`. You can use the `react-native-xcode.sh` script in `node_modules/react-native/scripts/` to generate that pre-bundled file. - - - -> When moving your app to production, the `NSURL` can point to a pre-bundled file on disk via something like `let mainBundle = NSBundle(URLForResource: "main" withExtension:"jsbundle")`. You can use the `react-native-xcode.sh` script in `node_modules/react-native/scripts/` to generate that pre-bundled file. - - - -##### 3. Wire Up - -Wire up the new link in the main menu to the newly added event handler method. - -![Event Path](/react-native/docs/assets/react-native-add-react-native-integration-wire-up.png) - -> One of the easier ways to do this is to open the view in the storyboard and right click on the new link. Select something such as the `Touch Up Inside` event, drag that to the storyboard and then select the created method from the list provided. - -### Test your integration - -You have now done all the basic steps to integrate React Native with your current application. Now we will start the React Native packager to build the `index.bundle` package and the server running on `localhost` to serve it. - -##### 1. Add App Transport Security exception - -Apple has blocked implicit cleartext HTTP resource loading. So we need to add the following our project's `Info.plist` (or equivalent) file. - -```xml -NSAppTransportSecurity - - NSExceptionDomains - - localhost - - NSTemporaryExceptionAllowsInsecureHTTPLoads - - - - -``` - -> App Transport Security is good for your users. Make sure to re-enable it prior to releasing your app for production. - -##### 2. Run the packager - -To run your app, you need to first start the development server. To do this, simply run the following command in the root directory of your React Native project: - -``` -$ npm start -``` - -##### 3. Run the app - -If you are using Xcode or your favorite editor, build and run your native iOS application as normal. Alternatively, you can run the app from the command line using: - -``` -# From the root of your project -$ react-native run-ios -``` - -In our sample application, you should see the link to the "High Scores" and then when you click on that you will see the rendering of your React Native component. - -Here is the _native_ application home screen: - -![Home Screen](/react-native/docs/assets/react-native-add-react-native-integration-example-home-screen.png) - -Here is the _React Native_ high score screen: - -![High Scores](/react-native/docs/assets/react-native-add-react-native-integration-example-high-scores.png) - -> If you are getting module resolution issues when running your application please see [this GitHub issue](https://github.com/facebook/react-native/issues/4968) for information and possible resolution. [This comment](https://github.com/facebook/react-native/issues/4968#issuecomment-220941717) seemed to be the latest possible resolution. - -### See the Code - - - -You can examine the code that added the React Native screen to our sample app on [GitHub](https://github.com/JoelMarcey/iOS-2048/commit/9ae70c7cdd53eb59f5f7c7daab382b0300ed3585). - - - -You can examine the code that added the React Native screen to our sample app on [GitHub](https://github.com/JoelMarcey/swift-2048/commit/13272a31ee6dd46dc68b1dcf4eaf16c1a10f5229). - - - -## Adding React Native to your app - -### Configuring maven - -Add the React Native dependency to your app's `build.gradle` file: - -```gradle -dependencies { - implementation 'com.android.support:appcompat-v7:27.1.1' - ... - implementation "com.facebook.react:react-native:+" // From node_modules -} -``` - -> If you want to ensure that you are always using a specific React Native version in your native build, replace `+` with an actual React Native version you've downloaded from `npm`. - -Add an entry for the local React Native maven directory to `build.gradle`. Be sure to add it to the "allprojects" block, above other maven repositories: - -```gradle -allprojects { - repositories { - maven { - // All of React Native (JS, Android binaries) is installed from npm - url "$rootDir/../node_modules/react-native/android" - } - ... - } - ... -} -``` - -> Make sure that the path is correct! You shouldn’t run into any “Failed to resolve: com.facebook.react:react-native:0.x.x" errors after running Gradle sync in Android Studio. - -### Configuring permissions - -Next, make sure you have the Internet permission in your `AndroidManifest.xml`: - - - -If you need to access to the `DevSettingsActivity` add to your `AndroidManifest.xml`: - - - -This is only used in dev mode when reloading JavaScript from the development server, so you can strip this in release builds if you need to. - -### Cleartext Traffic (API level 28+) - -> Starting with Android 9 (API level 28), cleartext traffic is disabled by default; this prevents your application from connecting to the React Native packager. The changes below allow cleartext traffic in debug builds. - -#### 1. Apply the `usesCleartextTraffic` option to your Debug `AndroidManifest.xml` - -```xml - - - - - -``` - -This is not required for Release builds. - -To learn more about Network Security Config and the cleartext traffic policy [see this link](https://developer.android.com/training/articles/security-config#CleartextTrafficPermitted). - -### Code integration - -Now we will actually modify the native Android application to integrate React Native. - -#### The React Native component - -The first bit of code we will write is the actual React Native code for the new "High Score" screen that will be integrated into our application. - -##### 1. Create a `index.js` file - -First, create an empty `index.js` file in the root of your React Native project. - -`index.js` is the starting point for React Native applications, and it is always required. It can be a small file that `require`s other file that are part of your React Native component or application, or it can contain all the code that is needed for it. In our case, we will just put everything in `index.js`. - -##### 2. Add your React Native code - -In your `index.js`, create your component. In our sample here, we will add simple `` component within a styled ``: - -```jsx -import React from 'react'; -import {AppRegistry, StyleSheet, Text, View} from 'react-native'; - -class HelloWorld extends React.Component { - render() { - return ( - - Hello, World - - ); - } -} -var styles = StyleSheet.create({ - container: { - flex: 1, - justifyContent: 'center', - }, - hello: { - fontSize: 20, - textAlign: 'center', - margin: 10, - }, -}); - -AppRegistry.registerComponent('MyReactNativeApp', () => HelloWorld); -``` - -##### 3. Configure permissions for development error overlay - -If your app is targeting the Android `API level 23` or greater, make sure you have the permission `android.permission.SYSTEM_ALERT_WINDOW` enabled for the development build. You can check this with `Settings.canDrawOverlays(this);`. This is required in dev builds because React Native development errors must be displayed above all the other windows. Due to the new permissions system introduced in the API level 23 (Android M), the user needs to approve it. This can be achieved by adding the following code to your Activity's in `onCreate()` method. - -```java -private final int OVERLAY_PERMISSION_REQ_CODE = 1; // Choose any value - -... - -if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!Settings.canDrawOverlays(this)) { - Intent intent = new Intent(Settings.ACTION_MANAGE_OVERLAY_PERMISSION, - Uri.parse("package:" + getPackageName())); - startActivityForResult(intent, OVERLAY_PERMISSION_REQ_CODE); - } -} -``` - -Finally, the `onActivityResult()` method (as shown in the code below) has to be overridden to handle the permission Accepted or Denied cases for consistent UX. Also, for integrating Native Modules which use `startActivityForResult`, we need to pass the result to the `onActivityResult` method of our `ReactInstanceManager` instance. - -```java -@Override -protected void onActivityResult(int requestCode, int resultCode, Intent data) { - if (requestCode == OVERLAY_PERMISSION_REQ_CODE) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { - if (!Settings.canDrawOverlays(this)) { - // SYSTEM_ALERT_WINDOW permission not granted - } - } - } - mReactInstanceManager.onActivityResult( this, requestCode, resultCode, data ); -} -``` - -#### The Magic: `ReactRootView` - -Let's add some native code in order to start the React Native runtime and tell it to render our JS component. 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. - -> If you are targetting Android version <5, use the `AppCompatActivity` class from the `com.android.support:appcompat` package instead of `Activity`. - -```java -public class MyReactActivity extends Activity implements DefaultHardwareBackBtnHandler { - private ReactRootView mReactRootView; - private ReactInstanceManager mReactInstanceManager; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - mReactRootView = new ReactRootView(this); - mReactInstanceManager = ReactInstanceManager.builder() - .setApplication(getApplication()) - .setCurrentActivity(this) - .setBundleAssetName("index.android.bundle") - .setJSMainModulePath("index") - .addPackage(new MainReactPackage()) - .setUseDeveloperSupport(BuildConfig.DEBUG) - .setInitialLifecycleState(LifecycleState.RESUMED) - .build(); - // The string here (e.g. "MyReactNativeApp") has to match - // the string in AppRegistry.registerComponent() in index.js - mReactRootView.startReactApplication(mReactInstanceManager, "MyReactNativeApp", null); - - setContentView(mReactRootView); - } - - @Override - public void invokeDefaultOnBackPressed() { - super.onBackPressed(); - } -} -``` - -> If you are using a starter kit for React Native, replace the "HelloWorld" string with the one in your index.js file (it’s the first argument to the `AppRegistry.registerComponent()` method). - -If you are using Android Studio, use `Alt + Enter` to add all missing imports in your MyReactActivity class. Be careful to use your package’s `BuildConfig` and not the one from the `facebook` package. - -We need set the theme of `MyReactActivity` to `Theme.AppCompat.Light.NoActionBar` because some React Native UI components rely on this theme. - -```xml - - -``` - -> A `ReactInstanceManager` can be shared by multiple activities and/or fragments. You will want to make your own `ReactFragment` or `ReactActivity` and have a singleton _holder_ that holds a `ReactInstanceManager`. When you need the `ReactInstanceManager` (e.g., to hook up the `ReactInstanceManager` to the lifecycle of those Activities or Fragments) use the one provided by the singleton. - -Next, we need to pass some activity lifecycle callbacks to the `ReactInstanceManager` and `ReactRootView`: - -```java -@Override -protected void onPause() { - super.onPause(); - - if (mReactInstanceManager != null) { - mReactInstanceManager.onHostPause(this); - } -} - -@Override -protected void onResume() { - super.onResume(); - - if (mReactInstanceManager != null) { - mReactInstanceManager.onHostResume(this, this); - } -} - -@Override -protected void onDestroy() { - super.onDestroy(); - - if (mReactInstanceManager != null) { - mReactInstanceManager.onHostDestroy(this); - } - if (mReactRootView != null) { - mReactRootView.unmountReactApplication(); - } -} -``` - -We also need to pass back button events to React Native: - -```java -@Override - public void onBackPressed() { - if (mReactInstanceManager != null) { - mReactInstanceManager.onBackPressed(); - } else { - super.onBackPressed(); - } -} -``` - -This allows JavaScript to control what happens when the user presses the hardware back button (e.g. to implement navigation). When JavaScript doesn't handle the back button press, your `invokeDefaultOnBackPressed` method will be called. By default this simply finishes your `Activity`. - -Finally, we need to hook up the dev menu. By default, this is activated by (rage) shaking the device, but this is not very useful in emulators. So we make it show when you press the hardware menu button (use `Ctrl + M` if you're using Android Studio emulator): - -```java -@Override -public boolean onKeyUp(int keyCode, KeyEvent event) { - if (keyCode == KeyEvent.KEYCODE_MENU && mReactInstanceManager != null) { - mReactInstanceManager.showDevOptionsDialog(); - return true; - } - return super.onKeyUp(keyCode, event); -} -``` - -Now your activity is ready to run some JavaScript code. - -### Test your integration - -You have now done all the basic steps to integrate React Native with your current application. Now we will start the React Native packager to build the `index.bundle` package and the server running on localhost to serve it. - -##### 1. Run the packager - -To run your app, you need to first start the development server. To do this, simply run the following command in the root directory of your React Native project: - -``` -$ yarn start -``` - -##### 2. Run the app - -Now build and run your Android app as normal. - -Once you reach your React-powered activity inside the app, it should load the JavaScript code from the development server and display: - -![Screenshot](/react-native/docs/assets/EmbeddedAppAndroid.png) - -### Creating a release build in Android Studio - -You can use Android Studio to create your release builds too! It’s as easy as creating release builds of your previously-existing native Android app. There’s just one additional step, which you’ll have to do before every release build. You need to execute the following to create a React Native bundle, which will be included with your native Android app: - -``` -$ react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/com/your-company-name/app-package-name/src/main/assets/index.android.bundle --assets-dest android/com/your-company-name/app-package-name/src/main/res/ -``` - -> Don’t forget to replace the paths with correct ones and create the assets folder if it doesn’t exist. - -Now just create a release build of your native app from within Android Studio as usual and you should be good to go! - - - -### Now what? - -At this point you can continue developing your app as usual. Refer to our [debugging](debugging.md) and [deployment](running-on-device.md) docs to learn more about working with React Native. diff --git a/website/versioned_docs/version-0.60/javascript-environment.md b/website/versioned_docs/version-0.60/javascript-environment.md deleted file mode 100644 index 25473b10a9e..00000000000 --- a/website/versioned_docs/version-0.60/javascript-environment.md +++ /dev/null @@ -1,90 +0,0 @@ ---- -id: version-0.60-javascript-environment -title: JavaScript Environment -original_id: javascript-environment ---- - -## JavaScript Runtime - -When using React Native, you're going to be running your JavaScript code in two environments: - -- In most cases, React Native will use [JavaScriptCore](http://trac.webkit.org/wiki/JavaScriptCore), the JavaScript engine that powers Safari. Note that on iOS, JavaScriptCore does not use JIT due to the absence of writable executable memory in iOS apps. -- When using Chrome debugging, all JavaScript code runs within Chrome itself, communicating with native code via WebSockets. Chrome uses [V8](https://v8.dev/) as its JavaScript engine. - -While both environments are very similar, you may end up hitting some inconsistencies. We're likely going to experiment with other JavaScript engines in the future, so it's best to avoid relying on specifics of any runtime. - -## JavaScript Syntax Transformers - -Syntax transformers make writing code more enjoyable by allowing you to use new JavaScript syntax without having to wait for support on all interpreters. - -React Native ships with the [Babel JavaScript compiler](https://babeljs.io). Check [Babel documentation](https://babeljs.io/docs/plugins/#transform-plugins) on its supported transformations for more details. - -A full list of React Native's enabled transformations can be found in [metro-react-native-babel-preset](https://github.com/facebook/metro/tree/master/packages/metro-react-native-babel-preset). - -ES5 - -- Reserved Words: `promise.catch(function() { });` - -ES6 - -- [Arrow functions](http://babeljs.io/docs/learn-es2015/#arrows): ` this.setState({pressed: true})} />` -- [Block scoping](https://babeljs.io/docs/learn-es2015/#let-const): `let greeting = 'hi';` -- [Call spread](http://babeljs.io/docs/learn-es2015/#default-rest-spread): `Math.max(...array);` -- [Classes](http://babeljs.io/docs/learn-es2015/#classes): `class C extends React.Component { render() { return ; } }` -- [Constants](https://babeljs.io/docs/learn-es2015/#let-const): `const answer = 42;` -- [Destructuring](http://babeljs.io/docs/learn-es2015/#destructuring): `var {isActive, style} = this.props;` -- [for...of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of): `for (var num of [1, 2, 3]) {};` -- [Modules](http://babeljs.io/docs/learn-es2015/#modules): `import React, { Component } from 'react';` -- [Computed Properties](http://babeljs.io/docs/learn-es2015/#enhanced-object-literals): `var key = 'abc'; var obj = {[key]: 10};` -- [Object Concise Method](http://babeljs.io/docs/learn-es2015/#enhanced-object-literals): `var obj = { method() { return 10; } };` -- [Object Short Notation](http://babeljs.io/docs/learn-es2015/#enhanced-object-literals): `var name = 'vjeux'; var obj = { name };` -- [Rest Params](https://github.com/sebmarkbage/ecmascript-rest-spread): `function(type, ...args) {};` -- [Template Literals](http://babeljs.io/docs/learn-es2015/#template-strings): `` var who = 'world'; var str = `Hello ${who}`; `` - -ES8 - -- [Function Trailing Comma](https://github.com/jeffmo/es-trailing-function-commas): `function f(a, b, c,) {};` -- [Async Functions](https://github.com/tc39/ecmascript-asyncawait): `async function doStuffAsync() { const foo = await doOtherStuffAsync(); };` - -Stage 3 - -- [Object Spread](https://github.com/tc39/proposal-object-rest-spread): `var extended = { ...obj, a: 10 };` -- [Static class fields](https://github.com/tc39/proposal-static-class-features): `class CustomDate { static epoch = new CustomDate(0); }` -- [Optional Chaining](https://github.com/tc39/proposal-optional-chaining): `var name = obj.user?.name;` - -Specific - -- [JSX](https://reactjs.org/docs/jsx-in-depth.html): `` -- [Flow](https://flowtype.org/): `function foo(x: ?number): string {};` -- [TypeScript](https://flowtype.org/): `function foo(x: number | undefined): string {};` -- [Babel Template](https://babeljs.io/docs/en/babel-template): allows AST templating - -## Polyfills - -Many standards functions are also available on all the supported JavaScript runtimes. - -Browser - -- [console.{log, warn, error, info, trace, table, group, groupEnd}](https://developer.chrome.com/devtools/docs/console-api) -- [CommonJS require](https://nodejs.org/docs/latest/api/modules.html) -- [XMLHttpRequest, fetch](network.md#content) -- [{set, clear}{Timeout, Interval, Immediate}, {request, cancel}AnimationFrame](timers.md#content) - -ES6 - -- [Object.assign](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign) -- String.prototype.{[startsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith), [endsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith), [repeat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat), [includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes)} -- [Array.from](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from) -- Array.prototype.{[find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find), [findIndex](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex)} - -ES7 - -- Array.prototype.{[includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)} - -ES8 - -- Object.{[entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries), [values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values)} - -Specific - -- `__DEV__` diff --git a/website/versioned_docs/version-0.60/more-resources.md b/website/versioned_docs/version-0.60/more-resources.md deleted file mode 100644 index c2061248e6a..00000000000 --- a/website/versioned_docs/version-0.60/more-resources.md +++ /dev/null @@ -1,44 +0,0 @@ ---- -id: version-0.60-more-resources -title: More Resources -original_id: more-resources ---- - -If you just read through this website, you should be able to build a pretty cool React Native app. But React Native isn't just a product made by one company - it's a community of thousands of developers. So if you're interested in React Native, here's some related stuff you might want to check out. - -## Popular Libraries - -If you're using React Native, you probably already know about [React](https://facebook.github.io/react/). So I feel a bit silly mentioning this. But if you haven't, check out React - it's the best way to build a modern website. - -One common question is how to handle the "state" of your React Native application. The most popular library for this is [Redux](http://redux.js.org/). Don't be afraid of how often Redux uses the word "reducer" - it's a pretty simple library, and there's also a nice [series of videos](https://egghead.io/courses/getting-started-with-redux) explaining it. - -If you're looking for a library that does a specific thing, check out [Awesome React Native](http://www.awesome-react-native.com/), a curated list of components that also has demos, articles, and other stuff. - -## Examples - -Try out apps from the [Showcase](/react-native/showcase/) to see what React Native is capable of! There are also some [example apps on GitHub](https://github.com/ReactNativeNews/React-Native-Apps). You can run the apps on a simulator or device, and you can see the source code for these apps, which is neat. - -The folks who built the app for Facebook's F8 conference also [open-sourced the code](https://github.com/fbsamples/f8app) and wrote up a [detailed series of tutorials](http://makeitopen.com/). This is useful if you want a more in-depth example that's more realistic than most sample apps out there. - -## Extending React Native - -- Fellow developers write and publish React Native modules to npm and open source them on GitHub. -- Making modules helps grow the React Native ecosystem and community. We recommend writing modules for your use cases and sharing them on npm. -- Read the guides on Native Modules ([iOS](native-modules-ios.md), [Android](native-modules-android.md)) and Native UI Components ([iOS](native-components-ios.md), [Android](native-components-android.md)) if you are interested in extending native functionality. -- Looking for a pre-built component? Check [JS.coach](https://js.coach/react-native) or [Native Directory](https://www.native.directory) to find what the community has been creating. - -## Development Tools - -[Nuclide](https://nuclide.io/) is the IDE that Facebook uses internally for JavaScript development. The killer feature of Nuclide is its debugging ability. It also has great inline Flow support. [VS Code](https://code.visualstudio.com/) is another IDE that is popular with JavaScript developers. - -[Ignite](https://github.com/infinitered/ignite) is a starter kit that uses Redux and a few different common UI libraries. It has a CLI to generate apps, components, and containers. If you like all of the individual tech choices, Ignite could be perfect for you. - -[App Center](https://appcenter.ms/) is a service from Microsoft that makes it easy to deploy live updates to your React Native app. If you don't like going through the app store process to deploy little tweaks, and you also don't like setting up your own backend, give App Center a try. - -[Expo](https://docs.expo.io) is a development environment plus application that focuses on letting you build React Native apps in the Expo development environment, without ever touching Xcode or Android Studio. If you wish React Native was even more JavaScripty and webby, check out Expo. - -[Yoga](https://yogalayout.com/) is a stand-alone layout engine that extends beyond React Native and allows product engineers to build layouts quickly for multiple platforms with a highly optimized open source layout engine designed with speed, size, and ease of use in mind. - -[Bugsnag](https://www.bugsnag.com/), [Microsoft App Center](https://appcenter.ms/), and [Sentry](https://sentry.io/welcome/) all provide excellent crash and error monitoring services for React and React Native apps. These services allow you to proactively monitor crashes and issues occurring on your apps in real time so you can fix them quickly and improve user experience. - -The [React Developer Tools](debugging.md#react-developer-tools) are great for debugging React and React Native apps. diff --git a/website/versioned_docs/version-0.60/native-components-ios.md b/website/versioned_docs/version-0.60/native-components-ios.md deleted file mode 100644 index d1457705995..00000000000 --- a/website/versioned_docs/version-0.60/native-components-ios.md +++ /dev/null @@ -1,512 +0,0 @@ ---- -id: version-0.60-native-components-ios -title: Native UI Components -original_id: native-components-ios ---- - -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. - -## iOS MapView example - -Let's say we want to add an interactive Map to our app - might as well use [`MKMapView`](https://developer.apple.com/library/prerelease/mac/documentation/MapKit/Reference/MKMapView_Class/index.html), 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 expose native views to the `RCTUIManager`, which delegates back to them to set and update the properties of the views as necessary. The `RCTViewManager`s are also typically the delegates for the views, sending events back to JavaScript via the bridge. - -Exposing a view is simple: - -- Subclass `RCTViewManager` to create a manager for your component. -- Add the `RCT_EXPORT_MODULE()` marker macro. -- Implement the `-(UIView *)view` method. - -```objectivec -// RNTMapManager.m -#import - -#import - -@interface RNTMapManager : RCTViewManager -@end - -@implementation RNTMapManager - -RCT_EXPORT_MODULE(RNTMap) - -- (UIView *)view -{ - return [[MKMapView alloc] init]; -} - -@end -``` - -**Note:** Do not attempt to set the `frame` or `backgroundColor` properties on the `UIView` instance that you expose through the `-view` method. React Native will overwrite the values set by your custom class in order to match your JavaScript component's layout props. If you need this granularity of control it might be better to wrap the `UIView` instance you want to style in another `UIView` and return the wrapper `UIView` instead. See [Issue 2948](https://github.com/facebook/react-native/issues/2948) for more context. - -> In the example above, we prefixed our class name with `RNT`. Prefixes are used to avoid name collisions with other frameworks. Apple frameworks use two-letter prefixes, and React Native uses `RCT` as a prefix. In order to avoid name collisions, we recommend using a three-letter prefix other than `RCT` in your own classes. - -Then you just need a little bit of JavaScript to make this a usable React component: - -```jsx -// MapView.js - -import { requireNativeComponent } from 'react-native'; - -// requireNativeComponent automatically resolves 'RNTMap' to 'RNTMapManager' -module.exports = requireNativeComponent('RNTMap'); - -// MyApp.js - -import MapView from './MapView.js'; - -... - -render() { - return ; -} -``` - -Make sure to use `RNTMap` here. We want to require the manager here, which will expose the view of our manager for use in Javascript. - -**Note:** When rendering, don't forget to stretch the view, otherwise you'll be staring at a blank screen. - -```jsx - render() { - return ; - } -``` - -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 :( - -## Properties - -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 zooming and specify the visible region. Disabling zoom is a simple boolean, so we add this one line: - -```objectivec -// RNTMapManager.m -RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL) -``` - -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 zooming, we set the property in JS: - -```jsx -// MyApp.js - -``` - -To document the properties (and which values they accept) of our MapView component we'll add a wrapper component and document the interface with React `PropTypes`: - -```jsx -// MapView.js -import PropTypes from 'prop-types'; -import React from 'react'; -import {requireNativeComponent} from 'react-native'; - -class MapView extends React.Component { - render() { - return ; - } -} - -MapView.propTypes = { - /** - * A Boolean value that determines whether the user may use pinch - * gestures to zoom in and out of the map. - */ - zoomEnabled: PropTypes.bool, -}; - -var RNTMap = requireNativeComponent('RNTMap', MapView); - -module.exports = MapView; -``` - -Now we have a nicely documented wrapper component that is easy to work with. Note that we changed `requireNativeComponent`'s second argument from `null` to the new `MapView` wrapper component. This allows the infrastructure to verify that the propTypes match the native props in order to reduce the chances of mismatches between the Objective-C and JavaScript code. - -Next, let's add the more complex `region` prop. We start by adding the native code: - -```objectivec -// RNTMapManager.m -RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView) -{ - [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES]; -} -``` - -Ok, this is more complicated than the simple `BOOL` case we had before. Now we have a `MKCoordinateRegion` type that needs a conversion function, and we have custom code so that the view will animate when we set the region from JS. Within the function body that we provide, `json` refers to the raw value that has been passed from JS. There is also a `view` variable which gives us access to the manager's view instance, and a `defaultView` that we use to reset the property back to the default value if JS sends us a null sentinel. - -You could write any conversion function you want for your view - here is the implementation for `MKCoordinateRegion` via a category on `RCTConvert`. It uses an already existing category of ReactNative `RCTConvert+CoreLocation`: - -```objectivec -// RNTMapManager.m - -#import "RCTConvert+Mapkit.m" - -// RCTConvert+Mapkit.h - -#import -#import -#import -#import - -@interface RCTConvert (Mapkit) - -+ (MKCoordinateSpan)MKCoordinateSpan:(id)json; -+ (MKCoordinateRegion)MKCoordinateRegion:(id)json; - -@end - -@implementation RCTConvert(MapKit) - -+ (MKCoordinateSpan)MKCoordinateSpan:(id)json -{ - json = [self NSDictionary:json]; - return (MKCoordinateSpan){ - [self CLLocationDegrees:json[@"latitudeDelta"]], - [self CLLocationDegrees:json[@"longitudeDelta"]] - }; -} - -+ (MKCoordinateRegion)MKCoordinateRegion:(id)json -{ - return (MKCoordinateRegion){ - [self CLLocationCoordinate2D:json], - [self MKCoordinateSpan:json] - }; -} - -@end -``` - -These conversion functions are designed to safely process any JSON that the JS might throw at them by displaying "RedBox" errors and returning standard initialization values when missing keys or other developer errors are encountered. - -To finish up support for the `region` prop, we need to document it in `propTypes` (or we'll get an error that the native prop is undocumented), then we can set it just like any other prop: - -```jsx -// MapView.js - -MapView.propTypes = { - /** - * A Boolean value that determines whether the user may use pinch - * gestures to zoom in and out of the map. - */ - zoomEnabled: PropTypes.bool, - - /** - * The region to be displayed by the map. - * - * The region is defined by the center coordinates and the span of - * coordinates to display. - */ - region: PropTypes.shape({ - /** - * Coordinates for the center of the map. - */ - latitude: PropTypes.number.isRequired, - longitude: PropTypes.number.isRequired, - - /** - * Distance between the minimum and the maximum latitude/longitude - * to be displayed. - */ - latitudeDelta: PropTypes.number.isRequired, - longitudeDelta: PropTypes.number.isRequired, - }), -}; - -// MyApp.js - -render() { - var region = { - latitude: 37.48, - longitude: -122.16, - latitudeDelta: 0.1, - longitudeDelta: 0.1, - }; - return ( - - ); -} -``` - -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 your native component will have some special properties that you don't want to be 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 add them to the `nativeOnly` option, e.g. - -```jsx -var RCTSwitch = requireNativeComponent('RCTSwitch', Switch, { - nativeOnly: {onChange: true}, -}); -``` - -## Events - -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? - -Until now we've just returned a `MKMapView` instance from our manager's `-(UIView *)view` method. We can't add new properties to `MKMapView` so we have to create a new subclass from `MKMapView` which we use for our View. We can then add a `onRegionChange` callback on this subclass: - -```objectivec -// RNTMapView.h - -#import - -#import - -@interface RNTMapView: MKMapView - -@property (nonatomic, copy) RCTBubblingEventBlock onRegionChange; - -@end - -// RNTMapView.m - -#import "RNTMapView.h" - -@implementation RNTMapView - -@end -``` - -Note that all `RCTBubblingEventBlock` must be prefixed with `on`. Next, declare an event handler property on `RNTMapManager`, make it a delegate for all the views it exposes, and forward events to JS by calling the event handler block from the native view. - -```objectivec{9,17,31-48} -// RNTMapManager.m - -#import -#import - -#import "RNTMapView.h" -#import "RCTConvert+Mapkit.m" - -@interface RNTMapManager : RCTViewManager -@end - -@implementation RNTMapManager - -RCT_EXPORT_MODULE() - -RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL) -RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTBubblingEventBlock) - -RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView) -{ - [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES]; -} - -- (UIView *)view -{ - RNTMapView *map = [RNTMapView new]; - map.delegate = self; - return map; -} - -#pragma mark MKMapViewDelegate - -- (void)mapView:(RNTMapView *)mapView regionDidChangeAnimated:(BOOL)animated -{ - if (!mapView.onRegionChange) { - return; - } - - MKCoordinateRegion region = mapView.region; - mapView.onRegionChange(@{ - @"region": @{ - @"latitude": @(region.center.latitude), - @"longitude": @(region.center.longitude), - @"latitudeDelta": @(region.span.latitudeDelta), - @"longitudeDelta": @(region.span.longitudeDelta), - } - }); -} -@end -``` - -In the delegate method `-mapView:regionDidChangeAnimated:` the event handler block is called on the corresponding view with the region data. Calling the `onRegionChange` event handler block results in calling the same callback prop in JavaScript. This callback is invoked with the raw event, which we typically process in the wrapper component to make a simpler API: - -```jsx -// MapView.js - -class MapView extends React.Component { - _onRegionChange = (event) => { - if (!this.props.onRegionChange) { - return; - } - - // process raw event... - this.props.onRegionChange(event.nativeEvent); - } - render() { - return ( - - ); - } -} -MapView.propTypes = { - /** - * Callback that is called continuously when the user is dragging the map. - */ - onRegionChange: PropTypes.func, - ... -}; - -// MyApp.js - -class MyApp extends React.Component { - onRegionChange(event) { - // Do stuff with event.region.latitude, etc. - } - - render() { - var region = { - latitude: 37.48, - longitude: -122.16, - latitudeDelta: 0.1, - longitudeDelta: 0.1, - }; - return ( - - ); - } -} -``` - -## Handling multiple native views - -A React Native view can have more than one child view in the view tree eg. - -```jsx - - - -