diff --git a/.alexignore b/.alexignore new file mode 100644 index 00000000000..639d702ed56 --- /dev/null +++ b/.alexignore @@ -0,0 +1,69 @@ +# The Code of Conduct calls out language that can't be used so it's not linted. +CODE_OF_CONDUCT.md + +# We will handle the blog posts after the main docs are linted. +website/blog/ + +# The version docs are actively being linted. +# If you want to lint one of these directories, remove it from the list here and then run: +# `yarn lintv website/versioned_docs/version-{version number}/` +# Once you fix all of the errors, commit all of the changes including this file. +# +# To be considerate to the reviewer, please submit each version in different PRs. +website/versioned_docs/version-0.5/ +website/versioned_docs/version-0.6/ +website/versioned_docs/version-0.7/ +website/versioned_docs/version-0.8/ +website/versioned_docs/version-0.9/ +website/versioned_docs/version-0.10/ +website/versioned_docs/version-0.11/ +website/versioned_docs/version-0.12/ +website/versioned_docs/version-0.13/ +website/versioned_docs/version-0.14/ +website/versioned_docs/version-0.15/ +website/versioned_docs/version-0.16/ +website/versioned_docs/version-0.17/ +website/versioned_docs/version-0.18/ +website/versioned_docs/version-0.19/ +website/versioned_docs/version-0.20/ +website/versioned_docs/version-0.21/ +website/versioned_docs/version-0.22/ +website/versioned_docs/version-0.23/ +website/versioned_docs/version-0.24/ +website/versioned_docs/version-0.25/ +website/versioned_docs/version-0.26/ +website/versioned_docs/version-0.27/ +website/versioned_docs/version-0.28/ +website/versioned_docs/version-0.29/ +website/versioned_docs/version-0.30/ +website/versioned_docs/version-0.31/ +website/versioned_docs/version-0.32/ +website/versioned_docs/version-0.33/ +website/versioned_docs/version-0.34/ +website/versioned_docs/version-0.35/ +website/versioned_docs/version-0.36/ +website/versioned_docs/version-0.37/ +website/versioned_docs/version-0.38/ +website/versioned_docs/version-0.39/ +website/versioned_docs/version-0.40/ +website/versioned_docs/version-0.41/ +website/versioned_docs/version-0.42/ +website/versioned_docs/version-0.43/ +website/versioned_docs/version-0.44/ +website/versioned_docs/version-0.45/ +website/versioned_docs/version-0.46/ +website/versioned_docs/version-0.47/ +website/versioned_docs/version-0.48/ +website/versioned_docs/version-0.49/ +website/versioned_docs/version-0.50/ +website/versioned_docs/version-0.51/ +website/versioned_docs/version-0.52/ +website/versioned_docs/version-0.53/ +website/versioned_docs/version-0.54/ +website/versioned_docs/version-0.55/ +website/versioned_docs/version-0.56/ +website/versioned_docs/version-0.57/ +website/versioned_docs/version-0.58/ +website/versioned_docs/version-0.59/ +website/versioned_docs/version-0.60/ +website/versioned_docs/version-0.61/ diff --git a/.alexrc.js b/.alexrc.js new file mode 100644 index 00000000000..8e57d66334e --- /dev/null +++ b/.alexrc.js @@ -0,0 +1,18 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +exports.allow = [ + // We frequently refer to form props by their name "disabled". + // Ideally we would alex-ignore only the valid uses (PRs accepted). + "invalid", + + // Unfortunately "watchman" is a library name that we depend on. + "watchman-watchwoman" +]; + +// Use a "maybe" level of profanity instead of the default "unlikely". +exports.profanitySureness = 1; diff --git a/.circleci/config.yml b/.circleci/config.yml index 338eb960e72..ad8501c23e1 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -50,10 +50,10 @@ jobs: - ~/react-native-website # -------------------------------------------------- - # JOB: test_website - # Test website can be built and has no lint issues. + # JOB: test + # Test that the website can be built. # -------------------------------------------------- - test_website: + test: executor: node8 working_directory: ~/react-native-website/website steps: @@ -67,6 +67,17 @@ jobs: if [ ! -f build/react-native/index.html ]; then exit 1; fi + # -------------------------------------------------- + # JOB: lint + # Lint the docs. + # -------------------------------------------------- + language_lint: + executor: node8 + working_directory: ~/react-native-website/website + steps: + - restore_cache_checkout + - run_yarn + - run: yarn lint # -------------------------------------------------- # JOB: deploy_website @@ -101,8 +112,13 @@ workflows: jobs: - setup - # Test website - - test_website: + # Run tests + - test: + requires: + - setup + + # Run lints + - language_lint: requires: - setup diff --git a/docs/accessibility.md b/docs/accessibility.md index eeb5ee019e7..6799c898248 100644 --- a/docs/accessibility.md +++ b/docs/accessibility.md @@ -49,7 +49,7 @@ In the above example, the `accessibilityLabel` on the TouchableOpacity element w #### accessibilityHint (iOS, Android) -An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not obvious from the accessibility label. +An accessibility hint helps users understand what will happen when they perform an action on the accessibility element when that result is not clear from the accessibility label. To use, set the `accessibilityHint` property to a custom string on your View, Text or Touchable: @@ -185,7 +185,7 @@ 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. +In the above example, the yellow layout and its descendants are completely invisible to TalkBack and all other accessibility services. So we can use overlapping views with the same parent without confusing TalkBack. ### Accessibility Actions diff --git a/docs/animated.md b/docs/animated.md index ce465c6a570..2fc36285be8 100644 --- a/docs/animated.md +++ b/docs/animated.md @@ -3,9 +3,9 @@ id: animated title: Animated --- -The `Animated` library is designed to make animations fluid, powerful, and easy to build and maintain. `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. +The `Animated` library is designed to make animations fluid, powerful, and painless to build and maintain. `Animated` focuses on declarative relationships between inputs and outputs, with configurable transforms in between, and `start`/`stop` methods to control time-based animation execution. -The simplest workflow for creating an animation is to create an `Animated.Value`, hook it up to one or more style attributes of an animated component, and then drive updates via animations using `Animated.timing()`: +The most basic workflow for creating an animation is to create an `Animated.Value`, hook it up to one or more style attributes of an animated component, and then drive updates via animations using `Animated.timing()`: ```jsx Animated.timing( @@ -33,7 +33,7 @@ There are two value types you can use with `Animated`: `Animated` provides three types of animation types. Each animation type provides a particular animation curve that controls how your values animate from their initial value to the final value: - [`Animated.decay()`](animated.md#decay) starts with an initial velocity and gradually slows to a stop. -- [`Animated.spring()`](animated.md#spring) provides a simple spring physics model. +- [`Animated.spring()`](animated.md#spring) provides a basic spring physics model. - [`Animated.timing()`](animated.md#timing) animates a value over time using [easing functions](easing.md). In most cases, you will be using `timing()`. By default, it uses a symmetric easeInOut curve that conveys the gradual acceleration of an object to full speed and concludes by gradually decelerating to a stop. @@ -50,7 +50,7 @@ You can use the native driver by specifying `useNativeDriver: true` in your anim ### Animatable components -Only animatable components can be animated. These special components do the magic of binding the animated values to the properties, and do targeted native updates to avoid the cost of the react render and reconciliation process on every frame. They also handle cleanup on unmount so they are safe by default. +Only animatable components can be animated. These unique components do the magic of binding the animated values to the properties, and do targeted native updates to avoid the cost of the react render and reconciliation process on every frame. They also handle cleanup on unmount so they are safe by default. - [`createAnimatedComponent()`](animated.md#createanimatedcomponent) can be used to make a component animatable. @@ -72,7 +72,7 @@ Animations can also be combined in complex ways using composition functions: - [`Animated.sequence()`](animated.md#sequence) starts the animations in order, waiting for each to complete before starting the next. - [`Animated.stagger()`](animated.md#stagger) starts animations in order and in parallel, but with successive delays. -Animations can also be chained together simply by setting the `toValue` of one animation to be another `Animated.Value`. See [Tracking dynamic values](animations.md#tracking-dynamic-values) in the Animations guide. +Animations can also be chained together by setting the `toValue` of one animation to be another `Animated.Value`. See [Tracking dynamic values](animations.md#tracking-dynamic-values) in the Animations guide. By default, if one animation is stopped or interrupted, then all other animations in the group are also stopped. @@ -169,14 +169,14 @@ Config is an object that may have the following options. Note that you can only define one of bounciness/speed, tension/friction, or stiffness/damping/mass, but not more than one: -The friction/tension or bounciness/speed options match the spring model in [Facebook Pop](https://github.com/facebook/pop), [Rebound](http://facebook.github.io/rebound/), and [Origami](http://origami.design/). +The friction/tension or bounciness/speed options match the spring model in [`Facebook Pop`](https://github.com/facebook/pop), [Rebound](http://facebook.github.io/rebound/), and [Origami](http://origami.design/). - `friction`: Controls "bounciness"/overshoot. Default 7. - `tension`: Controls speed. Default 40. - `speed`: Controls speed of the animation. Default 12. - `bounciness`: Controls bounciness. Default 8. -Specifying stiffness/damping/mass as parameters makes `Animated.spring` use an analytical spring model based on the motion equations of a [damped harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). This behavior is slightly more precise and faithful to the physics behind spring dynamics, and closely mimics the implementation in iOS's CASpringAnimation primitive. +Specifying stiffness/damping/mass as parameters makes `Animated.spring` use an analytical spring model based on the motion equations of a [damped harmonic oscillator](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). This behavior is slightly more precise and faithful to the physics behind spring dynamics, and closely mimics the implementation in iOS's CASpringAnimation. - `stiffness`: The spring stiffness coefficient. Default 100. - `damping`: Defines how the spring’s motion should be damped due to the forces of friction. Default 10. @@ -344,7 +344,7 @@ Config is an object that may have the following options: static forkEvent(event, listener) ``` -Advanced imperative API for snooping on animated events that are passed in through props. It permits to add a new javascript listener to an existing `AnimatedEvent`. If `animatedEvent` is a simple javascript listener, it will merge the 2 listeners into a single one, and if `animatedEvent` is null/undefined, it will assign the javascript listener directly. Use values directly where possible. +Advanced imperative API for snooping on animated events that are passed in through props. It permits to add a new javascript listener to an existing `AnimatedEvent`. If `animatedEvent` is a javascript listener, it will merge the 2 listeners into a single one, and if `animatedEvent` is null/undefined, it will assign the javascript listener directly. Use values directly where possible. --- diff --git a/docs/animations.md b/docs/animations.md index 5aee7826a5c..67fe68403f6 100644 --- a/docs/animations.md +++ b/docs/animations.md @@ -9,7 +9,7 @@ React Native provides two complementary animation systems: [`Animated`](animatio ## `Animated` API -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. +The [`Animated`](animated.md) API is designed 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 `start`/`stop` methods to control time-based animation execution. `Animated` exports six animatable component types: `View`, `Text`, `Image`, `ScrollView`, `FlatList` and `SectionList`, but you can also create your own using `Animated.createAnimatedComponent()`. @@ -58,7 +58,7 @@ export default () => { Let's break down what's happening here. In the `FadeInView` constructor, a new `Animated.Value` called `fadeAnim` is initialized as part of `state`. The opacity property on the `View` is mapped to this animated value. Behind the scenes, the numeric value is extracted and used to set opacity. -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. +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, only 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. @@ -84,7 +84,7 @@ Take a look at the [Configuring animations](animated.md#configuring-animations) ### Composing animations -Animations can be combined and played in sequence or in parallel. Sequential animations can play immediately after the previous animation has finished, or they can start after a specified delay. The `Animated` API provides several methods, such as `sequence()` and `delay()`, each of which simply take an array of animations to execute and automatically calls `start()`/`stop()` as needed. +Animations can be combined and played in sequence or in parallel. Sequential animations can play immediately after the previous animation has finished, or they can start after a specified delay. The `Animated` API provides several methods, such as `sequence()` and `delay()`, each of which take an array of animations to execute and automatically calls `start()`/`stop()` as needed. For example, the following animation coasts to a stop, then it springs back while twirling in parallel: @@ -132,7 +132,7 @@ Animated.spring(a, { Each property can be run through an interpolation first. An interpolation maps input ranges to output ranges, typically using a linear interpolation but also supports easing functions. By default, it will extrapolate the curve beyond the ranges given, but you can also have it clamp the output value. -A simple mapping to convert a 0-1 range to a 0-100 range would be: +A basic mapping to convert a 0-1 range to a 0-100 range would be: ```jsx value.interpolate({ @@ -141,7 +141,7 @@ value.interpolate({ }); ``` -For example, you may want to think about your `Animated.Value` as going from 0 to 1, but animate the position from 150px to 0px and the opacity from 0 to 1. This can easily be done by modifying `style` from the example above like so: +For example, you may want to think about your `Animated.Value` as going from 0 to 1, but animate the position from 150px to 0px and the opacity from 0 to 1. This can be done by modifying `style` from the example above like so: ```jsx style={{ @@ -194,7 +194,7 @@ value.interpolate({ ### Tracking dynamic values -Animated values can also track other values. Just set the `toValue` of an animation to another animated value instead of a plain number. For example, a "Chat Heads" animation like the one used by Messenger on Android could be implemented with a `spring()` pinned on another animated value, or with `timing()` and a `duration` of 0 for rigid tracking. They can also be composed with interpolations: +Animated values can also track other values by setting the `toValue` of an animation to another animated value instead of a plain number. For example, a "Chat Heads" animation like the one used by Messenger on Android could be implemented with a `spring()` pinned on another animated value, or with `timing()` and a `duration` of 0 for rigid tracking. They can also be composed with interpolations: ```jsx Animated.spring(follower, {toValue: leader}).start(); @@ -206,7 +206,7 @@ Animated.timing(opacity, { }).start(); ``` -The `leader` and `follower` animated values would be implemented using `Animated.ValueXY()`. `ValueXY` is a handy way to deal with 2D interactions, such as panning or dragging. It is a simple wrapper that basically contains two `Animated.Value` instances and some helper functions that call through to them, making `ValueXY` a drop-in replacement for `Value` in many cases. It allows us to track both x and y values in the example above. +The `leader` and `follower` animated values would be implemented using `Animated.ValueXY()`. `ValueXY` is a handy way to deal with 2D interactions, such as panning or dragging. It is a basic wrapper that contains two `Animated.Value` instances and some helper functions that call through to them, making `ValueXY` a drop-in replacement for `Value` in many cases. It allows us to track both x and y values in the example above. ### Tracking gestures @@ -239,7 +239,7 @@ onPanResponderMove={Animated.event( ### Responding to the current animation value -You may notice that there is no obvious way to read the current value while animating. This is because the value may only be known in the native runtime due to optimizations. If you need to run JavaScript in response to the current value, there are two approaches: +You may notice that there is no clear way to read the current value while animating. This is because the value may only be known in the native runtime due to optimizations. If you need to run JavaScript in response to the current value, there are two approaches: - `spring.stopAnimation(callback)` will stop the animation and invoke `callback` with the final value. This is useful when making gesture transitions. - `spring.addListener(callback)` will invoke `callback` asynchronously while the animation is running, providing a recent value. This is useful for triggering state changes, for example snapping a bobble to a new option as the user drags it closer, because these larger state changes are less sensitive to a few frames of lag compared to continuous gestures like panning which need to run at 60 fps. @@ -250,7 +250,7 @@ You may notice that there is no obvious way to read the current value while anim 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. +Using the native driver for normal animations is straightforward. You can add `useNativeDriver: true` to the animation config when starting it. ```jsx Animated.timing(this.state.animatedValue, { diff --git a/docs/app-extensions.md b/docs/app-extensions.md index 9ce20889811..2c3b7dd39f6 100644 --- a/docs/app-extensions.md +++ b/docs/app-extensions.md @@ -7,7 +7,7 @@ App extensions let you provide custom functionality and content outside of your ## Memory use in extensions -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. +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 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://www.youtube.com/watch?v=GqXMqn6MXrM) to learn more about this topic. @@ -17,7 +17,7 @@ The memory limit of a Today widget is 16 MB. As it happens, Today widget impleme  -Always make sure to test your app extensions in a real device, but be aware that this may not be sufficient, especially when dealing with Today widgets. Debug-configured builds are more likely to exceed the memory limits, while release-configured builds don't fail right away. We highly recommend that you use [Xcode's Instruments](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/index.html) to analyze your real world memory usage, as it's very likely that your release-configured build is very close to the 16 MB limit. In situations like these, it is easy to go over the 16 MB limit by performing common operations, such as fetching data from an API. +Always make sure to test your app extensions in a real device, but be aware that this may not be sufficient, especially when dealing with Today widgets. Debug-configured builds are more likely to exceed the memory limits, while release-configured builds don't fail right away. We highly recommend that you use [Xcode's Instruments](https://developer.apple.com/library/content/documentation/DeveloperTools/Conceptual/InstrumentsUserGuide/index.html) to analyze your real world memory usage, as it's very likely that your release-configured build is very close to the 16 MB limit. In situations like these, you can quickly go over the 16 MB limit by performing common operations, such as fetching data from an API. To experiment with the limits of React Native Today widget implementations, try extending the example project in [react-native-today-widget](https://github.com/matejkriz/react-native-today-widget/). diff --git a/docs/appstate.md b/docs/appstate.md index 19f8f9b2fa4..0e360defa28 100644 --- a/docs/appstate.md +++ b/docs/appstate.md @@ -85,7 +85,7 @@ addEventListener(type, handler); Add a handler to AppState changes by listening to the `change` event type and providing the handler -TODO: now that AppState is a subclass of NativeEventEmitter, we could deprecate `addEventListener` and `removeEventListener` and just use `addListener` and `listener.remove()` directly. That will be a breaking change though, as both the method and event names are different (addListener events are currently required to be globally unique). +TODO: now that AppState is a subclass of NativeEventEmitter, we could deprecate `addEventListener` and `removeEventListener` and use `addListener` and `listener.remove()` directly. That will be a breaking change though, as both the method and event names are different (addListener events are currently required to be globally unique). --- diff --git a/docs/asyncstorage.md b/docs/asyncstorage.md index 764684ad376..01120c8d9b1 100644 --- a/docs/asyncstorage.md +++ b/docs/asyncstorage.md @@ -5,13 +5,13 @@ title: AsyncStorage > **Deprecated.** Use [react-native-community/react-native-async-storage](https://github.com/react-native-community/react-native-async-storage) instead. -`AsyncStorage` is a simple, unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage. +`AsyncStorage` is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage. It is recommended that you use an abstraction on top of `AsyncStorage` instead of `AsyncStorage` directly for anything more than light usage since it operates globally. On iOS, `AsyncStorage` is backed by native code that stores small values in a serialized dictionary and larger values in separate files. On Android, `AsyncStorage` will use either [RocksDB](http://rocksdb.org/) or SQLite based on what is available. -The `AsyncStorage` JavaScript code is a simple facade that provides a clear JavaScript API, real `Error` objects, and simple non-multi functions. Each method in the API returns a `Promise` object. +The `AsyncStorage` JavaScript code is a facade that provides a clear JavaScript API, real `Error` objects, and non-multi functions. Each method in the API returns a `Promise` object. Importing the `AsyncStorage` library: diff --git a/docs/building-for-apple-tv.md b/docs/building-for-apple-tv.md index 42ee6927ec7..67796e43470 100644 --- a/docs/building-for-apple-tv.md +++ b/docs/building-for-apple-tv.md @@ -3,7 +3,7 @@ id: building-for-apple-tv title: Building For TV Devices --- -TV devices support has been implemented with the intention of making existing React Native applications "just work" on Apple TV and Android TV, with few or no changes needed in the JavaScript code for the applications. +TV devices support has been implemented with the intention of making existing React Native applications work on Apple TV and Android TV, with few or no changes needed in the JavaScript code for the applications.
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. +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 can pick one to start with, since the setup is a bit different.