diff --git a/.circleci/config.yml b/.circleci/config.yml
index ae294ea2e20..52c5678d300 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -25,6 +25,7 @@ commands:
- run:
name: Yarn Install
command: yarn install --no-progress --non-interactive --cache-folder ~/.cache/yarn
+ working_directory: ~/react-native-website
- save_cache:
paths:
- node_modules
diff --git a/.gitignore b/.gitignore
index 6e85513bdcb..45da9c7e3e9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,6 @@ cnwebsite/scripts/sync-api-docs/generatedComponentApiDocs.js
cnwebsite/scripts/sync-api-docs/extracted.json
sync-api-docs/generatedComponentApiDocs.js
sync-api-docs/extracted.json
+
+scripts/lint-examples/out/
+
diff --git a/.prettierrc b/.prettierrc
index 43f7d62dd47..11998292dbf 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -15,13 +15,13 @@
{
"files": "*.md",
"options": {
- "arrowParens": "always",
- "bracketSpacing": true,
+ "arrowParens": "avoid",
+ "bracketSpacing": false,
"bracketSameLine": true,
"printWidth": 66,
"proseWrap": "preserve",
"singleQuote": true,
- "trailingComma": "none",
+ "trailingComma": "all",
"endOfLine": "auto"
}
},
diff --git a/README.md b/README.md
index 9dd7e5d7d4e..043f068b37f 100644
--- a/README.md
+++ b/README.md
@@ -45,7 +45,7 @@ If you are looking for the source code of the [React Native Archive website](htt
## đ Overview
If you would like to **_contribute an edit or addition to the docs,_** read through our [style guide](STYLEGUIDE.md) before you write anything.
-Almost all our content is generated from markdown files you can find in the `docs`, `website/architecure` and `website/contibuting` directories.
+Almost all our content is generated from markdown files you can find in the `docs`, `website/architecture` and `website/contributing` directories.
**_To edit the internals of how the site is built,_** you may want to get familiarized with how the site is built. The React Native website is a static site generated using [Docusaurus](https://docusaurus.io/).
The website configuration can be found in the `website` directory. Visit the Docusaurus website to learn more about all the available configuration options.
@@ -109,7 +109,7 @@ As mentioned above, the `docs` folder contains the source files for docs from "G
The doc files for the "Architecture" and "Contribution" tabs are located inside `website` in the respective directories (unversioned/static docs).
In most cases, you will only want to edit the files within those directories.
-If you're adding a new doc or you need to alter the order the docs appear in the sidebar, take a look at the `sidebars.json`, `sidebarsArchitecture.json` and `sidebarsContributing.json` files in the `website` directory. The sidebar files contains a list of document ids that should match those defined in the header metadata (aka frontmatter) of the docs markdown files.
+If you're adding a new doc or you need to alter the order the docs appear in the sidebar, take a look at the `sidebars.json`, `sidebarsArchitecture.json` and `sidebarsContributing.json` files in the `website` directory. The sidebar files contain a list of document ids that should match those defined in the header metadata (aka frontmatter) of the docs markdown files.
### Versioned docs
@@ -117,7 +117,7 @@ Part of the React Native website is versioned to allow users to go back and see
> **_Note:_** Do not edit the auto-generated files within `versioned_docs` or `versioned_sidebars` unless you are sure it is necessary. Edits made to older versions will not be propagated to newer versions of the versioned docs.
-Docusaurus keeps track of the list of versions for the site in the `website/versions.json` file. The ordering of the versions in this file should be in reverse chronological order.
+Docusaurus keeps track of the list of versions for the site in the `website/versions.json` file. The ordering of versions in this file should be in reverse chronological order.
#### Cutting a new version
diff --git a/docs/_getting-started-linux-android.md b/docs/_getting-started-linux-android.md
index 839c6882c65..1c10384763b 100644
--- a/docs/_getting-started-linux-android.md
+++ b/docs/_getting-started-linux-android.md
@@ -49,21 +49,21 @@ 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_SDK_ROOT 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` or `$HOME/.bashrc` (if you are using `zsh` then `~/.zprofile` or `~/.zshrc`) config file:
```shell
-export ANDROID_SDK_ROOT=$HOME/Library/Android/Sdk
-export PATH=$PATH:$ANDROID_SDK_ROOT/emulator
-export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools
+export ANDROID_HOME=$HOME/Android/Sdk
+export PATH=$PATH:$ANDROID_HOME/emulator
+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` for `bash` or `source $HOME/.zprofile` to load the config into your current shell. Verify that ANDROID_SDK_ROOT has been set by running `echo $ANDROID_SDK_ROOT` and the appropriate directories have been added to your path by running `echo $PATH`.
+Type `source $HOME/.bash_profile` for `bash` or `source $HOME/.zprofile` to load the config into your current shell. Verify that ANDROID_HOME has been set by running `echo $ANDROID_HOME` and the appropriate directories have 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**.
@@ -97,11 +97,7 @@ If you want to start a new project with a specific React Native version, you can
npx react-native init AwesomeProject --version X.XX.X
```
-You can also start a project with a custom React Native template, like TypeScript, with `--template` argument:
-
-```shell
-npx react-native init AwesomeTSProject --template react-native-template-typescript
-```
+You can also start a project with a custom React Native template with the `--template` argument.
Preparing the Android device
diff --git a/docs/_getting-started-macos-android.md b/docs/_getting-started-macos-android.md
index eada9f7e420..9e1d1e3022a 100644
--- a/docs/_getting-started-macos-android.md
+++ b/docs/_getting-started-macos-android.md
@@ -69,19 +69,19 @@ 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_SDK_ROOT 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 `~/.zprofile` or `~/.zshrc` (if you are using `bash`, then `~/.bash_profile` or `~/.bashrc`) config file:
```shell
-export ANDROID_SDK_ROOT=$HOME/Library/Android/sdk
-export PATH=$PATH:$ANDROID_SDK_ROOT/emulator
-export PATH=$PATH:$ANDROID_SDK_ROOT/platform-tools
+export ANDROID_HOME=$HOME/Library/Android/sdk
+export PATH=$PATH:$ANDROID_HOME/emulator
+export PATH=$PATH:$ANDROID_HOME/platform-tools
```
-Run `source ~/.zprofile` (or `source ~/.bash_profile` for `bash`) to load the config into your current shell. Verify that ANDROID_SDK_ROOT has been set by running `echo $ANDROID_SDK_ROOT` and the appropriate directories have been added to your path by running `echo $PATH`.
+Run `source ~/.zprofile` (or `source ~/.bash_profile` for `bash`) to load the config into your current shell. Verify that ANDROID_HOME has been set by running `echo $ANDROID_HOME` and the appropriate directories have 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**.
@@ -109,11 +109,7 @@ If you want to start a new project with a specific React Native version, you can
npx react-native init AwesomeProject --version X.XX.X
```
-You can also start a project with a custom React Native template, like TypeScript, with `--template` argument:
-
-```shell
-npx react-native init AwesomeTSProject --template react-native-template-typescript
-```
+You can also start a project with a custom React Native template with the `--template` argument.
Preparing the Android device
diff --git a/docs/_getting-started-macos-ios.md b/docs/_getting-started-macos-ios.md
index 7359e734983..93a316dce4f 100644
--- a/docs/_getting-started-macos-ios.md
+++ b/docs/_getting-started-macos-ios.md
@@ -1,4 +1,4 @@
-import M1Cocoapods from './\_markdown-m1-cocoapods.mdx'; import RemoveGlobalCLI from './\_remove-global-cli.md';
+import RemoveGlobalCLI from './\_remove-global-cli.md';
## Installing dependencies
@@ -70,8 +70,6 @@ To install a simulator, open Xcode > Preferences... and select
For more information, please visit [CocoaPods Getting Started guide](https://guides.cocoapods.org/using/getting-started.html).
-
-
### React Native Command Line Interface
React Native has a built-in command line interface. Rather than install and manage a specific version of the CLI globally, we recommend you access the current version at runtime using `npx`, which ships with Node.js. With `npx react-native `, the current stable version of the CLI will be downloaded and executed at the time the command is run.
@@ -107,11 +105,7 @@ If you want to start a new project with a specific React Native version, you can
npx react-native init AwesomeProject --version X.XX.X
```
-You can also start a project with a custom React Native template, like TypeScript, with `--template` argument:
-
-```shell
-npx react-native init AwesomeTSProject --template react-native-template-typescript
-```
+You can also start a project with a custom React Native template with the `--template` argument.
> **Note** If the above command is failing, you may have old version of `react-native` or `react-native-cli` installed globally on your pc. Try uninstalling the cli and run the cli using `npx`.
diff --git a/docs/_getting-started-windows-android.md b/docs/_getting-started-windows-android.md
index 1ae3a3c9c21..230190b7a62 100644
--- a/docs/_getting-started-windows-android.md
+++ b/docs/_getting-started-windows-android.md
@@ -128,11 +128,7 @@ If you want to start a new project with a specific React Native version, you can
npx react-native init AwesomeProject --version X.XX.X
```
-You can also start a project with a custom React Native template, like TypeScript, with `--template` argument:
-
-```shell
-npx react-native init AwesomeTSProject --template react-native-template-typescript
-```
+You can also start a project with a custom React Native template with the `--template` argument.
Preparing the Android device
diff --git a/docs/_integration-with-exisiting-apps-java.md b/docs/_integration-with-exisiting-apps-java.md
index f090f7083be..2e5b61eefb5 100644
--- a/docs/_integration-with-exisiting-apps-java.md
+++ b/docs/_integration-with-exisiting-apps-java.md
@@ -41,7 +41,7 @@ $ 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".
+> warning "react-native@0.70.5" has unmet peer dependency "react@18.1.0"
This is OK, it means we also need to install React:
@@ -55,41 +55,54 @@ Add `node_modules/` to your `.gitignore` file.
## Adding React Native to your app
-### Configuring maven
+### Configuring Gradle
-Add the React Native and JSC dependency to your app's `build.gradle` file:
+React Native uses the React Native Gradle Plugin to configure your dependencies and project setup.
-```gradle
-dependencies {
- implementation "com.android.support:appcompat-v7:27.1.1"
- ...
- implementation "com.facebook.react:react-native:+" // From node_modules
- implementation "org.webkit:android-jsc:+"
-}
-```
+First, let's edit your `settings.gradle` file by adding this line:
-> 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`.
+```groovy
+includeBuild('../node_modules/react-native-gradle-plugin')
+```
-Add an entry for the local React Native and JSC maven directories to the top-level `build.gradle`. Be sure to add it to the âallprojectsâ block, above other maven repositories:
+Then you need to open your top level `build.gradle` and include this line:
-```gradle
-allprojects {
+```diff
+buildscript {
repositories {
- maven {
- // All of React Native (JS, Android binaries) is installed from npm
- url "$rootDir/../node_modules/react-native/android"
- }
- maven {
- // Android JSC is installed from npm
- url("$rootDir/../node_modules/jsc-android/dist")
- }
- ...
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath("com.android.tools.build:gradle:7.3.1")
++ classpath("com.facebook.react:react-native-gradle-plugin")
}
- ...
}
```
-> 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.
+This makes sure the React Native Gradle Plugin is available inside your project.
+Finally, add those lines inside your app's `build.gradle` file (it's a different `build.gradle` file inside your app folder):
+
+```diff
+apply plugin: "com.android.application"
++apply plugin: "com.facebook.react"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ // Other dependencies here
++ implementation "com.facebook.react:react-android"
++ implementation "com.facebook.react:hermes-android"
+}
+```
+
+Those depedencies are available on `mavenCentral()` so make sure you have it defined in your `repositories{}` block.
+
+:::info
+We intentionally don't specify the version for those `implementation` dependencies as the React Native Gradle Plugin will take care of it. If you don't use the React Native Gradle Plugin, you'll have to specify version manually.
+:::
### Enable native modules autolinking
@@ -156,12 +169,7 @@ In your `index.js`, create your component. In our sample here, we will add a ` {
return (
@@ -173,18 +181,18 @@ const HelloWorld = () => {
var styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: 'center'
+ justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
- margin: 10
- }
+ margin: 10,
+ },
});
AppRegistry.registerComponent(
'MyReactNativeApp',
- () => HelloWorld
+ () => HelloWorld,
);
```
@@ -371,7 +379,11 @@ Once you reach your React-powered activity inside the app, it should load the Ja
### Creating a release build in Android Studio
-You can use Android Studio to create your release builds too! Itâs as quick as creating release builds of your previously-existing native Android app. Thereâs 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:
+You can use Android Studio to create your release builds too! Itâs as quick as creating release builds of your previously-existing native Android app.
+
+If you use the React Native Gradle Plugin as described above, everything should work when running app from Android Studio.
+
+If you're not using the React Native Gradle Plugin, thereâs 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:
```shell
$ npx 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/
diff --git a/docs/_integration-with-exisiting-apps-objc.md b/docs/_integration-with-exisiting-apps-objc.md
index 893187c9b91..220245e9761 100644
--- a/docs/_integration-with-exisiting-apps-objc.md
+++ b/docs/_integration-with-exisiting-apps-objc.md
@@ -1,4 +1,4 @@
-import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; import M1Cocoapods from './\_markdown-m1-cocoapods.mdx';
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
## Key Concepts
@@ -186,8 +186,6 @@ Pod installation complete! There are 3 dependencies from the Podfile and 1 total
> If this fails with errors mentioning `xcrun`, make sure that in Xcode in **Preferences > Locations** the Command Line Tools are assigned.
-
-
### 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.
@@ -208,15 +206,10 @@ In your `index.js`, create your component. In our sample here, we will add a ` {
- const contents = scores.map((score) => (
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const RNHighScores = ({scores}) => {
+ const contents = scores.map(score => (
{score.name}:{score.value}
{'\n'}
@@ -237,18 +230,18 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: 'center',
alignItems: 'center',
- backgroundColor: '#FFFFFF'
+ backgroundColor: '#FFFFFF',
},
highScoresTitle: {
fontSize: 20,
textAlign: 'center',
- margin: 10
+ margin: 10,
},
scores: {
textAlign: 'center',
color: '#333333',
- marginBottom: 5
- }
+ marginBottom: 5,
+ },
});
// Module name
diff --git a/docs/_integration-with-exisiting-apps-swift.md b/docs/_integration-with-exisiting-apps-swift.md
index a1c8ea18456..cb3a21aa1a6 100644
--- a/docs/_integration-with-exisiting-apps-swift.md
+++ b/docs/_integration-with-exisiting-apps-swift.md
@@ -1,5 +1,3 @@
-import M1Cocoapods from './\_markdown-m1-cocoapods.mdx';
-
## Key Concepts
The keys to integrating React Native components into your iOS application are to:
@@ -154,8 +152,6 @@ Pod installation complete! There are 3 dependencies from the Podfile and 1 total
> 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.
@@ -176,15 +172,10 @@ In your `index.js`, create your component. In our sample here, we will add a ` {
- const contents = scores.map((score) => (
+import {AppRegistry, StyleSheet, Text, View} from 'react-native';
+
+const RNHighScores = ({scores}) => {
+ const contents = scores.map(score => (
{score.name}:{score.value}
{'\n'}
@@ -205,18 +196,18 @@ const styles = StyleSheet.create({
flex: 1,
justifyContent: 'center',
alignItems: 'center',
- backgroundColor: '#FFFFFF'
+ backgroundColor: '#FFFFFF',
},
highScoresTitle: {
fontSize: 20,
textAlign: 'center',
- margin: 10
+ margin: 10,
},
scores: {
textAlign: 'center',
color: '#333333',
- marginBottom: 5
- }
+ marginBottom: 5,
+ },
});
// Module name
diff --git a/docs/_integration-with-existing-apps-kotlin.md b/docs/_integration-with-existing-apps-kotlin.md
index 9500da50e71..0ab43d37f3c 100644
--- a/docs/_integration-with-existing-apps-kotlin.md
+++ b/docs/_integration-with-existing-apps-kotlin.md
@@ -41,7 +41,7 @@ $ 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".
+> warning "react-native@0.70.5" has unmet peer dependency "react@18.1.0"
This is OK, it means we also need to install React:
@@ -55,58 +55,54 @@ Add `node_modules/` to your `.gitignore` file.
## Adding React Native to your app
-### Configuring maven
+### Configuring Gradle
-Add the React Native and JSC dependency to your app's `build.gradle` file:
+React Native uses the React Native Gradle Plugin to configure your dependencies and project setup.
-```gradle
-dependencies {
- implementation "com.android.support:appcompat-v7:27.1.1"
- ...
- implementation "com.facebook.react:react-native:+" // From node_modules
- implementation "org.webkit:android-jsc:+"
-}
-```
+First, let's edit your `settings.gradle` file by adding this line:
-> 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`.
+```groovy
+includeBuild('../node_modules/react-native-gradle-plugin')
+```
-Add an entry for the local React Native and JSC maven directories to the top-level `settings.gradle`. Be sure to add it to the âdependencyResolutionManagementâ block, above other maven repositories:
+Then you need to open your top level `build.gradle` and include this line:
-```gradle
-dependencyResolutionManagement {
- ...
+```diff
+buildscript {
repositories {
- ...
- maven {
- url "$rootDir/../node_modules/react-native/android"
- }
- maven {
- url("$rootDir/../node_modules/jsc-android/dist")
- }
+ google()
+ mavenCentral()
+ }
+ dependencies {
+ classpath("com.android.tools.build:gradle:7.3.1")
++ classpath("com.facebook.react:react-native-gradle-plugin")
}
}
```
-> If your project has the dependency repositories configured in the top-level `build.gradle`, be sure to add the entries to the âallprojectsâ block above other maven repositories:
+This makes sure the React Native Gradle Plugin is available inside your project.
+Finally, add those lines inside your app's `build.gradle` file (it's a different `build.gradle` file inside your app folder):
-```gradle
-allprojects {
- repositories {
- maven {
- // All of React Native (JS, Android binaries) is installed from npm
- url "$rootDir/../node_modules/react-native/android"
- }
- maven {
- // Android JSC is installed from npm
- url("$rootDir/../node_modules/jsc-android/dist")
- }
- ...
- }
- ...
+```diff
+apply plugin: "com.android.application"
++apply plugin: "com.facebook.react"
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ // Other dependencies here
++ implementation "com.facebook.react:react-android"
++ implementation "com.facebook.react:hermes-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.
+Those depedencies are available on `mavenCentral()` so make sure you have it defined in your `repositories{}` block.
+
+:::info
+We intentionally don't specify the version for those `implementation` dependencies as the React Native Gradle Plugin will take care of it. If you don't use the React Native Gradle Plugin, you'll have to specify version manually.
+:::
### Enable native modules autolinking
@@ -173,12 +169,7 @@ In your `index.js`, create your component. In our sample here, we will add a ` {
return (
@@ -190,18 +181,18 @@ const HelloWorld = () => {
var styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: 'center'
+ justifyContent: 'center',
},
hello: {
fontSize: 20,
textAlign: 'center',
- margin: 10
- }
+ margin: 10,
+ },
});
AppRegistry.registerComponent(
'MyReactNativeApp',
- () => HelloWorld
+ () => HelloWorld,
);
```
@@ -364,7 +355,11 @@ Once you reach your React-powered activity inside the app, it should load the Ja
### Creating a release build in Android Studio
-You can use Android Studio to create your release builds too! Itâs as quick as creating release builds of your previously-existing native Android app. Thereâs 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:
+You can use Android Studio to create your release builds too! Itâs as quick as creating release builds of your previously-existing native Android app.
+
+If you use the React Native Gradle Plugin as described above, everything should work when running app from Android Studio.
+
+If you're not using the React Native Gradle Plugin, thereâs 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:
```shell
$ npx 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/
diff --git a/docs/_markdown-m1-cocoapods.mdx b/docs/_markdown-m1-cocoapods.mdx
deleted file mode 100644
index 41161b15791..00000000000
--- a/docs/_markdown-m1-cocoapods.mdx
+++ /dev/null
@@ -1,11 +0,0 @@
-
- Note for Mac M1 users
-
-Mac M1 architecture is not directly compatible with Cocoapods. If you encounter issues when installing pods, you can solve it by running:
-
-- `sudo arch -x86_64 gem install ffi`
-- `arch -x86_64 pod install`
-
-These commands install the `ffi` package, to load dynamically-linked libraries and let you run the `pod install` properly, and runs `pod install` with the proper architecture.
-
-
diff --git a/docs/accessibility.md b/docs/accessibility.md
index de91a016c42..39e8ae64a04 100644
--- a/docs/accessibility.md
+++ b/docs/accessibility.md
@@ -18,7 +18,7 @@ When `true`, indicates that the view is an accessibility element. When a view is
On Android, `accessible={true}` property for a react-native View will be translated into native `focusable={true}`.
-```jsx
+```tsx
text onetext two
@@ -33,7 +33,7 @@ When a view is marked as accessible, it is a good practice to set an accessibili
To use, set the `accessibilityLabel` property to a custom string on your View, Text or Touchable:
-```jsx
+```tsx
Label for Input FieldClick me
@@ -274,7 +274,7 @@ Defines a string value that labels an interactive element.
Identifies the element that labels the element it is applied to. The value of `aria-labelledby` should match the [`nativeID`](view.md#nativeid) of the related element:
-```jsx
+```tsx
Label for Input Field
@@ -293,6 +293,12 @@ Indicates that an element will be updated, and describes the types of updates th
- **polite** Accessibility services should announce changes to this view.
- **assertive** Accessibility services should interrupt ongoing speech to immediately announce changes to this view.
+| Type | Default |
+| ---------------------------------------- | ------- |
+| enum(`'assertive'`, `'off'`, `'polite'`) | `'off'` |
+
+---
+
### `aria-modal`
iOS
Boolean value indicating whether VoiceOver should ignore the elements within views that are siblings of the receiver.
@@ -313,15 +319,15 @@ Indicates whether a selectable element is currently selected or not.
In the case of two overlapping UI components with the same parent, default accessibility focus can have unpredictable behavior. The `importantForAccessibility` property will resolve this by controlling if a view fires accessibility events and if it is reported to accessibility services. It can be set to `auto`, `yes`, `no` and `no-hide-descendants` (the last value will force accessibility services to ignore the component and all of its children).
-```jsx
+```tsx
First layoutSecond layout
@@ -342,6 +348,40 @@ Use this property to assign a custom function to be called when someone activate
Assign this property to a custom function which will be called when someone performs the "magic tap" gesture, which is a double-tap with two fingers. A magic tap function should perform the most relevant action a user could take on a component. In the Phone app on iPhone, a magic tap answers a phone call, or ends the current one. If the selected element does not have an `onMagicTap` function, the system will traverse up the view hierarchy until it finds a view that does.
+### `role`
+
+`role` communicates the purpose of a component to the user of an assistive technology. Has precedence over the [`accessibilityRole`](accessibility#accessibilityrole) prop.
+
+`role` can be one of the following:
+
+- **alert** Used when an element contains important text to be presented to the user.
+- **button** Used when the element should be treated as a button.
+- **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.
+- **grid** Used with ScrollView, VirtualizedList, FlatList, or SectionList to represent a grid. Adds the in/out of grid announcements to the android GridView.
+- **heading** Used when an element acts as a header for a content section (e.g. the title of a navigation bar).
+- **img** Used when the element should be treated as an image. Can be combined with button or link, for example.
+- **link** Used when the element should be treated as a link.
+- **list** Used to identify a list of items.
+- **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.
+- **none** Used when the element has no role.
+- **presentation** Used when the element has no role.
+- **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.
+- **searchbox** Used when the text field element should also be treated as a search field.
+- **slider** Used when an element can be "adjusted" (e.g. a slider).
+- **spinbutton** Used to represent a button which opens a list of choices.
+- **summary** Used when an element can be used to provide a quick summary of current conditions in the app when the app first launches.
+- **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).
+
## 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:
@@ -371,15 +411,15 @@ The `label` field is optional for standard actions, and is often unused by assis
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
+```tsx
{
+ onAccessibilityAction={event => {
switch (event.nativeEvent.actionName) {
case 'cut':
Alert.alert('Alert', 'cut action success');
@@ -403,17 +443,13 @@ The `AccessibilityInfo` API allows you to determine whether or not a screen read
Sometimes it is useful to trigger an accessibility event on a UI component (i.e. when a custom view appears on a screen or set accessibility focus to a view). Native UIManager module exposes a method âsendAccessibilityEventâ for this purpose. It takes two arguments: view tag and a type of an event. The supported event types are `typeWindowStateChanged`, `typeViewFocused` and `typeViewClicked`.
-```jsx
-import {
- Platform,
- UIManager,
- findNodeHandle
-} from 'react-native';
+```tsx
+import {Platform, UIManager, findNodeHandle} from 'react-native';
if (Platform.OS === 'android') {
UIManager.sendAccessibilityEvent(
findNodeHandle(this),
- UIManager.AccessibilityEventTypes.typeViewFocused
+ UIManager.AccessibilityEventTypes.typeViewFocused,
);
}
```
diff --git a/docs/accessibilityinfo.md b/docs/accessibilityinfo.md
index 39fe88bcf58..0ba8355104c 100644
--- a/docs/accessibilityinfo.md
+++ b/docs/accessibilityinfo.md
@@ -13,8 +13,8 @@ Sometimes it's useful to know whether or not the device has a screen reader that
```SnackPlayer name=AccessibilityInfo%20Function%20Component%20Example&supportedPlatforms=android,ios
-import React, { useState, useEffect } from "react";
-import { AccessibilityInfo, View, Text, StyleSheet } from "react-native";
+import React, {useState, useEffect} from 'react';
+import {AccessibilityInfo, View, Text, StyleSheet} from 'react-native';
const App = () => {
const [reduceMotionEnabled, setReduceMotionEnabled] = useState(false);
@@ -22,28 +22,24 @@ const App = () => {
useEffect(() => {
const reduceMotionChangedSubscription = AccessibilityInfo.addEventListener(
- "reduceMotionChanged",
- reduceMotionEnabled => {
- setReduceMotionEnabled(reduceMotionEnabled);
- }
+ 'reduceMotionChanged',
+ isReduceMotionEnabled => {
+ setReduceMotionEnabled(isReduceMotionEnabled);
+ },
);
const screenReaderChangedSubscription = AccessibilityInfo.addEventListener(
- "screenReaderChanged",
- screenReaderEnabled => {
- setScreenReaderEnabled(screenReaderEnabled);
- }
+ 'screenReaderChanged',
+ isScreenReaderEnabled => {
+ setScreenReaderEnabled(isScreenReaderEnabled);
+ },
);
- AccessibilityInfo.isReduceMotionEnabled().then(
- reduceMotionEnabled => {
- setReduceMotionEnabled(reduceMotionEnabled);
- }
- );
- AccessibilityInfo.isScreenReaderEnabled().then(
- screenReaderEnabled => {
- setScreenReaderEnabled(screenReaderEnabled);
- }
- );
+ AccessibilityInfo.isReduceMotionEnabled().then(isReduceMotionEnabled => {
+ setReduceMotionEnabled(isReduceMotionEnabled);
+ });
+ AccessibilityInfo.isScreenReaderEnabled().then(isScreenReaderEnabled => {
+ setScreenReaderEnabled(isScreenReaderEnabled);
+ });
return () => {
reduceMotionChangedSubscription.remove();
@@ -54,24 +50,24 @@ const App = () => {
return (
- The reduce motion is {reduceMotionEnabled ? "enabled" : "disabled"}.
+ The reduce motion is {reduceMotionEnabled ? 'enabled' : 'disabled'}.
- The screen reader is {screenReaderEnabled ? "enabled" : "disabled"}.
+ The screen reader is {screenReaderEnabled ? 'enabled' : 'disabled'}.
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
status: {
- margin: 30
- }
+ margin: 30,
+ },
});
export default App;
@@ -80,9 +76,12 @@ export default App;
-```SnackPlayer name=AccessibilityInfo%20Class%20Component%20Example&supportedPlatforms=android,ios
-import React, { Component } from 'react';
-import { AccessibilityInfo, View, Text, StyleSheet } from 'react-native';
+
+
+
+```SnackPlayer name=AccessibilityInfo%20Class%20Component%20Example&supportedPlatforms=android,ios&ext=js
+import React, {Component} from 'react';
+import {AccessibilityInfo, View, Text, StyleSheet} from 'react-native';
class AccessibilityStatusExample extends Component {
state = {
@@ -94,21 +93,21 @@ class AccessibilityStatusExample extends Component {
this.reduceMotionChangedSubscription = AccessibilityInfo.addEventListener(
'reduceMotionChanged',
reduceMotionEnabled => {
- this.setState({ reduceMotionEnabled });
- }
+ this.setState({reduceMotionEnabled});
+ },
);
this.screenReaderChangedSubscription = AccessibilityInfo.addEventListener(
'screenReaderChanged',
screenReaderEnabled => {
- this.setState({ screenReaderEnabled });
- }
+ this.setState({screenReaderEnabled});
+ },
);
AccessibilityInfo.isReduceMotionEnabled().then(reduceMotionEnabled => {
- this.setState({ reduceMotionEnabled });
+ this.setState({reduceMotionEnabled});
});
AccessibilityInfo.isScreenReaderEnabled().then(screenReaderEnabled => {
- this.setState({ screenReaderEnabled });
+ this.setState({screenReaderEnabled});
});
}
@@ -147,6 +146,83 @@ const styles = StyleSheet.create({
export default AccessibilityStatusExample;
```
+
+
+
+```SnackPlayer name=AccessibilityInfo%20Class%20Component%20Example&supportedPlatforms=android,ios&ext=tsx
+import React, {Component} from 'react';
+import {AccessibilityInfo, View, Text, StyleSheet} from 'react-native';
+import type {EmitterSubscription} from 'react-native';
+
+class AccessibilityStatusExample extends Component {
+ reduceMotionChangedSubscription?: EmitterSubscription;
+ screenReaderChangedSubscription?: EmitterSubscription;
+
+ state = {
+ reduceMotionEnabled: false,
+ screenReaderEnabled: false,
+ };
+
+ componentDidMount() {
+ this.reduceMotionChangedSubscription = AccessibilityInfo.addEventListener(
+ 'reduceMotionChanged',
+ reduceMotionEnabled => {
+ this.setState({reduceMotionEnabled});
+ },
+ );
+ this.screenReaderChangedSubscription = AccessibilityInfo.addEventListener(
+ 'screenReaderChanged',
+ screenReaderEnabled => {
+ this.setState({screenReaderEnabled});
+ },
+ );
+
+ AccessibilityInfo.isReduceMotionEnabled().then(reduceMotionEnabled => {
+ this.setState({reduceMotionEnabled});
+ });
+ AccessibilityInfo.isScreenReaderEnabled().then(screenReaderEnabled => {
+ this.setState({screenReaderEnabled});
+ });
+ }
+
+ componentWillUnmount() {
+ this.reduceMotionChangedSubscription?.remove();
+ this.screenReaderChangedSubscription?.remove();
+ }
+
+ render() {
+ return (
+
+
+ The reduce motion is{' '}
+ {this.state.reduceMotionEnabled ? 'enabled' : 'disabled'}.
+
+
+ The screen reader is{' '}
+ {this.state.screenReaderEnabled ? 'enabled' : 'disabled'}.
+
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ status: {
+ margin: 30,
+ },
+});
+
+export default AccessibilityStatusExample;
+```
+
+
+
+
@@ -158,8 +234,13 @@ export default AccessibilityStatusExample;
### `addEventListener()`
-```jsx
-static addEventListener(eventName, handler)
+```tsx
+static addEventListener(
+ eventName: AccessibilityChangeEventName | AccessibilityAnnouncementEventName,
+ handler: (
+ event: AccessibilityChangeEvent | AccessibilityAnnouncementFinishedEvent,
+ ) => void,
+): EmitterSubscription;
```
Add an event handler. Supported events:
@@ -179,8 +260,8 @@ Add an event handler. Supported events:
### `announceForAccessibility()`
-```jsx
-static announceForAccessibility(announcement)
+```tsx
+static announceForAccessibility(announcement: string);
```
Post a string to be announced by the screen reader.
@@ -189,8 +270,11 @@ Post a string to be announced by the screen reader.
### `announceForAccessibilityWithOptions()`
-```jsx
-static announceForAccessibilityWithOptions(announcement, options)
+```tsx
+static announceForAccessibilityWithOptions(
+ announcement: string,
+ options: options: {queue?: boolean},
+);
```
Post a string to be announced by the screen reader with modification options. By default announcements will interrupt any existing speech, but on iOS they can be queued behind existing speech by setting `queue` to `true` in the options object.
@@ -206,8 +290,8 @@ Post a string to be announced by the screen reader with modification options. By
### `getRecommendedTimeoutMillis()`
Android
-```jsx
-static getRecommendedTimeoutMillis(originalTimeout)
+```tsx
+static getRecommendedTimeoutMillis(originalTimeout: number): Promise;
```
Gets the timeout in millisecond that the user needs.
@@ -223,8 +307,8 @@ This value is set in "Time to take action (Accessibility timeout)" of "Accessibi
### `isAccessibilityServiceEnabled()`
Android
-```jsx
-static isAccessibilityServiceEnabled(): Promise
+```tsx
+static isAccessibilityServiceEnabled(): Promise;
```
Check whether any accessibility service is enabled. This includes TalkBack but also any third-party accessibility app that may be installed. To only check whether TalkBack is enabled, use [isScreenReaderEnabled](#isscreenreaderenabled). Returns a promise which resolves to a boolean. The result is `true` when some accessibility services is enabled and `false` otherwise.
@@ -235,8 +319,8 @@ Check whether any accessibility service is enabled. This includes TalkBack but a
### `isBoldTextEnabled()`
iOS
-```jsx
-static isBoldTextEnabled()
+```tsx
+static isBoldTextEnabled(): Promise:
```
Query whether a bold text is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when bold text is enabled and `false` otherwise.
@@ -245,8 +329,8 @@ Query whether a bold text is currently enabled. Returns a promise which resolves
### `isGrayscaleEnabled()`
iOS
-```jsx
-static isGrayscaleEnabled()
+```tsx
+static isGrayscaleEnabled(): Promise;
```
Query whether grayscale is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when grayscale is enabled and `false` otherwise.
@@ -255,8 +339,8 @@ Query whether grayscale is currently enabled. Returns a promise which resolves t
### `isInvertColorsEnabled()`
iOS
-```jsx
-static isInvertColorsEnabled()
+```tsx
+static isInvertColorsEnabled(): Promise;
```
Query whether invert colors is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when invert colors is enabled and `false` otherwise.
@@ -265,8 +349,8 @@ Query whether invert colors is currently enabled. Returns a promise which resolv
### `isReduceMotionEnabled()`
-```jsx
-static isReduceMotionEnabled()
+```tsx
+static isReduceMotionEnabled(): Promise;
```
Query whether reduce motion is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when reduce motion is enabled and `false` otherwise.
@@ -275,8 +359,8 @@ Query whether reduce motion is currently enabled. Returns a promise which resolv
### `isReduceTransparencyEnabled()`
iOS
-```jsx
-static isReduceTransparencyEnabled()
+```tsx
+static isReduceTransparencyEnabled(): Promise;
```
Query whether reduce transparency is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when a reduce transparency is enabled and `false` otherwise.
@@ -285,8 +369,8 @@ Query whether reduce transparency is currently enabled. Returns a promise which
### `isScreenReaderEnabled()`
-```jsx
-static isScreenReaderEnabled()
+```tsx
+static isScreenReaderEnabled(): Promise;
```
Query whether a screen reader is currently enabled. Returns a promise which resolves to a boolean. The result is `true` when a screen reader is enabled and `false` otherwise.
@@ -295,28 +379,18 @@ Query whether a screen reader is currently enabled. Returns a promise which reso
### `prefersCrossFadeTransitions()`
iOS
-```jsx
-static prefersCrossFadeTransitions()
+```tsx
+static prefersCrossFadeTransitions(): Promise;
```
Query whether reduce motion and prefer cross-fade transitions settings are currently enabled. Returns a promise which resolves to a boolean. The result is `true` when prefer cross-fade transitions is enabled and `false` otherwise.
---
-### `removeEventListener()`
-
-```jsx
-static removeEventListener(eventName, handler)
-```
-
-> **Deprecated.** Use the `remove()` method on the event subscription returned by [`addEventListener()`](#addeventlistener).
-
----
-
### `setAccessibilityFocus()`
-```jsx
-static setAccessibilityFocus(reactTag)
+```tsx
+static setAccessibilityFocus(reactTag: number);
```
Set accessibility focus to a React component.
diff --git a/docs/actionsheetios.md b/docs/actionsheetios.md
index a56f4629f9e..fd060e0dec9 100644
--- a/docs/actionsheetios.md
+++ b/docs/actionsheetios.md
@@ -8,29 +8,29 @@ Displays native to iOS [Action Sheet](https://developer.apple.com/design/human-i
## Example
```SnackPlayer name=ActionSheetIOS&supportedPlatforms=ios
-import React, { useState } from "react";
-import { ActionSheetIOS, Button, StyleSheet, Text, View } from "react-native";
+import React, {useState} from 'react';
+import {ActionSheetIOS, Button, StyleSheet, Text, View} from 'react-native';
const App = () => {
- const [result, setResult] = useState("đŽ");
+ const [result, setResult] = useState('đŽ');
const onPress = () =>
ActionSheetIOS.showActionSheetWithOptions(
{
- options: ["Cancel", "Generate number", "Reset"],
+ options: ['Cancel', 'Generate number', 'Reset'],
destructiveButtonIndex: 2,
cancelButtonIndex: 0,
- userInterfaceStyle: 'dark'
+ userInterfaceStyle: 'dark',
},
buttonIndex => {
if (buttonIndex === 0) {
// cancel action
} else if (buttonIndex === 1) {
- setResult(Math.floor(Math.random() * 100) + 1);
+ setResult(String(Math.floor(Math.random() * 100) + 1));
} else if (buttonIndex === 2) {
- setResult("đŽ");
+ setResult('đŽ');
}
- }
+ },
);
return (
@@ -44,12 +44,12 @@ const App = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center"
+ justifyContent: 'center',
},
result: {
fontSize: 64,
- textAlign: "center"
- }
+ textAlign: 'center',
+ },
});
export default App;
@@ -61,8 +61,11 @@ export default App;
### `showActionSheetWithOptions()`
-```jsx
-static showActionSheetWithOptions(options, callback)
+```tsx
+static showActionSheetWithOptions: (
+ options: ActionSheetIOSOptions,
+ callback: (buttonIndex: number) => void,
+);
```
Display an iOS action sheet. The `options` object must contain one or more of:
@@ -82,18 +85,18 @@ The 'callback' function takes one parameter, the zero-based index of the selecte
Minimal example:
-```jsx
+```tsx
ActionSheetIOS.showActionSheetWithOptions(
{
options: ['Cancel', 'Remove'],
destructiveButtonIndex: 1,
- cancelButtonIndex: 0
+ cancelButtonIndex: 0,
},
- (buttonIndex) => {
+ buttonIndex => {
if (buttonIndex === 1) {
/* destructive action */
}
- }
+ },
);
```
@@ -101,8 +104,8 @@ ActionSheetIOS.showActionSheetWithOptions(
### `dismissActionSheet()`
-```jsx
-static dismissActionSheet()
+```tsx
+static dismissActionSheet();
```
Dismisses the most upper iOS action sheet presented, if no action sheet is present a warning is displayed.
@@ -111,8 +114,12 @@ Dismisses the most upper iOS action sheet presented, if no action sheet is prese
### `showShareActionSheetWithOptions()`
-```jsx
-static showShareActionSheetWithOptions(options, failureCallback, successCallback)
+```tsx
+static showShareActionSheetWithOptions: (
+ options: ShareActionSheetIOSOptions,
+ failureCallback: (error: Error) => void,
+ successCallback: (success: boolean, method: string) => void,
+);
```
Display the iOS share sheet. The `options` object should contain one or both of `message` and `url` and can additionally have a `subject` or `excludedActivityTypes`:
diff --git a/docs/activityindicator.md b/docs/activityindicator.md
index 33e05f8d587..6659c0c6a2f 100644
--- a/docs/activityindicator.md
+++ b/docs/activityindicator.md
@@ -13,8 +13,8 @@ Displays a circular loading indicator.
```SnackPlayer name=ActivityIndicator%20Function%20Component%20Example
-import React from "react";
-import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
+import React from 'react';
+import {ActivityIndicator, StyleSheet, View} from 'react-native';
const App = () => (
@@ -28,13 +28,13 @@ const App = () => (
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center"
+ justifyContent: 'center',
},
horizontal: {
- flexDirection: "row",
- justifyContent: "space-around",
- padding: 10
- }
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ padding: 10,
+ },
});
export default App;
@@ -44,8 +44,8 @@ export default App;
```SnackPlayer name=ActivityIndicator%20Class%20Component%20Example
-import React, { Component } from "react";
-import { ActivityIndicator, StyleSheet, Text, View } from "react-native";
+import React, {Component} from 'react';
+import {ActivityIndicator, StyleSheet, View} from 'react-native';
class App extends Component {
render() {
@@ -63,13 +63,13 @@ class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center"
+ justifyContent: 'center',
},
horizontal: {
- flexDirection: "row",
- justifyContent: "space-around",
- padding: 10
- }
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ padding: 10,
+ },
});
export default App;
diff --git a/docs/alert.md b/docs/alert.md
index a347205a57c..e90473e384d 100644
--- a/docs/alert.md
+++ b/docs/alert.md
@@ -17,56 +17,48 @@ This is an API that works both on Android and iOS and can show static alerts. Al
```SnackPlayer name=Alert%20Function%20Component%20Example&supportedPlatforms=ios,android
-import React, { useState } from "react";
-import { View, StyleSheet, Button, Alert } from "react-native";
+import React from 'react';
+import {View, StyleSheet, Button, Alert} from 'react-native';
const App = () => {
const createTwoButtonAlert = () =>
- Alert.alert(
- "Alert Title",
- "My Alert Msg",
- [
- {
- text: "Cancel",
- onPress: () => console.log("Cancel Pressed"),
- style: "cancel"
- },
- { text: "OK", onPress: () => console.log("OK Pressed") }
- ]
- );
+ Alert.alert('Alert Title', 'My Alert Msg', [
+ {
+ text: 'Cancel',
+ onPress: () => console.log('Cancel Pressed'),
+ style: 'cancel',
+ },
+ {text: 'OK', onPress: () => console.log('OK Pressed')},
+ ]);
const createThreeButtonAlert = () =>
- Alert.alert(
- "Alert Title",
- "My Alert Msg",
- [
- {
- text: "Ask me later",
- onPress: () => console.log("Ask me later pressed")
- },
- {
- text: "Cancel",
- onPress: () => console.log("Cancel Pressed"),
- style: "cancel"
- },
- { text: "OK", onPress: () => console.log("OK Pressed") }
- ]
- );
+ Alert.alert('Alert Title', 'My Alert Msg', [
+ {
+ text: 'Ask me later',
+ onPress: () => console.log('Ask me later pressed'),
+ },
+ {
+ text: 'Cancel',
+ onPress: () => console.log('Cancel Pressed'),
+ style: 'cancel',
+ },
+ {text: 'OK', onPress: () => console.log('OK Pressed')},
+ ]);
return (
-
-
+
+
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "space-around",
- alignItems: "center"
- }
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ },
});
export default App;
@@ -76,49 +68,41 @@ export default App;
```SnackPlayer name=Alert%20Class%20Component%20Example&supportedPlatforms=ios,android
-import React, { Component } from "react";
-import { View, StyleSheet, Button, Alert } from "react-native";
+import React, {Component} from 'react';
+import {View, StyleSheet, Button, Alert} from 'react-native';
class App extends Component {
createTwoButtonAlert = () =>
- Alert.alert(
- "Alert Title",
- "My Alert Msg",
- [
- {
- text: "Cancel",
- onPress: () => console.log("Cancel Pressed"),
- style: "cancel"
- },
- { text: "OK", onPress: () => console.log("OK Pressed") }
- ]
- );
+ Alert.alert('Alert Title', 'My Alert Msg', [
+ {
+ text: 'Cancel',
+ onPress: () => console.log('Cancel Pressed'),
+ style: 'cancel',
+ },
+ {text: 'OK', onPress: () => console.log('OK Pressed')},
+ ]);
createThreeButtonAlert = () =>
- Alert.alert(
- "Alert Title",
- "My Alert Msg",
- [
- {
- text: "Ask me later",
- onPress: () => console.log("Ask me later pressed")
- },
- {
- text: "Cancel",
- onPress: () => console.log("Cancel Pressed"),
- style: "cancel"
- },
- { text: "OK", onPress: () => console.log("OK Pressed") }
- ]
- );
+ Alert.alert('Alert Title', 'My Alert Msg', [
+ {
+ text: 'Ask me later',
+ onPress: () => console.log('Ask me later pressed'),
+ },
+ {
+ text: 'Cancel',
+ onPress: () => console.log('Cancel Pressed'),
+ style: 'cancel',
+ },
+ {text: 'OK', onPress: () => console.log('OK Pressed')},
+ ]);
render() {
return (
-
+
@@ -129,9 +113,9 @@ class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "space-around",
- alignItems: "center"
- }
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ },
});
export default App;
@@ -142,7 +126,7 @@ export default App;
## iOS
-On iOS you can specify any number of buttons. Each button can optionally specify a style or be emphasized, available options are represented by the [AlertButtonStyle](#alertbuttonstyle-ios) enum and the `isPreferred` field on [Buttons](alert#buttons).
+On iOS you can specify any number of buttons. Each button can optionally specify a style or be emphasized, available options are represented by the [AlertButtonStyle](#alertbuttonstyle-ios) enum and the `isPreferred` field on [AlertButton](alert#alertbutton).
## Android
@@ -152,34 +136,34 @@ On Android at most three buttons can be specified. Android has a concept of a ne
- Two buttons mean 'negative', 'positive' (such as 'Cancel', 'OK')
- Three buttons mean 'neutral', 'negative', 'positive' (such as 'Later', 'Cancel', 'OK')
-Alerts on Android can be dismissed by tapping outside of the alert box. It is disabled by default and can be enabled by providing an optional [Options](alert#options) parameter with the cancelable property set to `true` i.e. `{ cancelable: true }`.
+Alerts on Android can be dismissed by tapping outside of the alert box. It is disabled by default and can be enabled by providing an optional [Options](alert#options) parameter with the cancelable property set to `true` i.e. `{cancelable: true}`.
The cancel event can be handled by providing an `onDismiss` callback property inside the `options` parameter.
### Example
| string | The dialog's title. Passing `null` or empty string will hide the title. |
-| message | string | An optional message that appears below the dialog's title. |
-| buttons | [Buttons](alert#buttons) | An optional array containing buttons configuration. |
-| options | [Options](alert#options) | An optional Alert configuration. |
+| Name | Type | Description |
+| ------------------------------------------------------ | ---------------------------------- | ----------------------------------------------------------------------- |
+| title
Required
| string | The dialog's title. Passing `null` or empty string will hide the title. |
+| message | string | An optional message that appears below the dialog's title. |
+| buttons | [AlertButton](alert#alertbutton)[] | An optional array containing buttons configuration. |
+| options | [Options](alert#options) | An optional Alert configuration. |
---
### `prompt()`
iOS
-```jsx
-static prompt(title, message?, callbackOrButtons?, type?, defaultValue?, keyboardType?)
+```tsx
+static prompt: (
+ title: string,
+ message?: string,
+ callbackOrButtons?: ((text: string) => void) | AlertButton[],
+ type?: AlertType,
+ defaultValue?: string,
+ keyboardType?: string,
+);
```
Create and display a prompt to enter some text in form of Alert.
**Parameters:**
-| Name | Type | Description |
-| ------------------------------------------------------ | ------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| title
Required
| string | The dialog's title. |
-| message | string | An optional message that appears above the text input. |
-| callbackOrButtons | function[Buttons](alert#buttons) | If passed a function, it will be called with the prompt's value `(text: string) => void`, when the user taps 'OK'.If passed an array, buttons will be configured based on the array content. |
-| type | [AlertType](alert#alerttype-ios) | This configures the text input. |
-| defaultValue | string | The default text in text input. |
-| keyboardType | string | The keyboard type of first text field (if exists). One of TextInput [keyboardTypes](textinput#keyboardtype). |
-| options | [Options](alert#options) | An optional Alert configuration. |
+| Name | Type | Description |
+| ------------------------------------------------------ | ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| title
Required
| string | The dialog's title. |
+| message | string | An optional message that appears above the text input. |
+| callbackOrButtons | function[AlertButton](alert#alertButton)[] | If passed a function, it will be called with the prompt's value `(text: string) => void`, when the user taps 'OK'.If passed an array, buttons will be configured based on the array content. |
+| type | [AlertType](alert#alerttype-ios) | This configures the text input. |
+| defaultValue | string | The default text in text input. |
+| keyboardType | string | The keyboard type of first text field (if exists). One of TextInput [keyboardTypes](textinput#keyboardtype). |
+| options | [Options](alert#options) | An optional Alert configuration. |
---
@@ -283,9 +279,9 @@ An iOS Alert type.
---
-### Buttons
+### AlertButton
-Array of objects containing Alert buttons configuration.
+An object describing the configuration of a button in the alert.
| Type |
| ---------------- |
@@ -302,7 +298,7 @@ Array of objects containing Alert buttons configuration.
---
-### Options
+### AlertOptions
| Type |
| ------ |
diff --git a/docs/alertios.md b/docs/alertios.md
index e338397bbd6..c02fae7c76c 100644
--- a/docs/alertios.md
+++ b/docs/alertios.md
@@ -3,7 +3,7 @@ id: alertios
title: 'đ§ AlertIOS'
---
-> **Deprecated.** Use [`Alert`](alert) instead.
+> **Removed.** Use [`Alert`](alert) instead.
`AlertIOS` provides functionality to create an iOS alert dialog with a message or create a prompt for user input.
@@ -12,15 +12,15 @@ Creating an iOS alert:
```jsx
AlertIOS.alert(
'Sync Complete',
- 'All your data are belong to us.'
+ 'All your data are belong to us.',
);
```
Creating an iOS prompt:
```jsx
-AlertIOS.prompt('Enter a value', null, (text) =>
- console.log('You entered ' + text)
+AlertIOS.prompt('Enter a value', null, text =>
+ console.log('You entered ' + text),
);
```
@@ -59,13 +59,13 @@ AlertIOS.alert(
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
- style: 'cancel'
+ style: 'cancel',
},
{
text: 'Install',
- onPress: () => console.log('Install Pressed')
- }
- ]
+ onPress: () => console.log('Install Pressed'),
+ },
+ ],
);
```
@@ -100,15 +100,15 @@ AlertIOS.prompt(
{
text: 'Cancel',
onPress: () => console.log('Cancel Pressed'),
- style: 'cancel'
+ style: 'cancel',
},
{
text: 'OK',
- onPress: (password) =>
- console.log('OK Pressed, password: ' + password)
- }
+ onPress: password =>
+ console.log('OK Pressed, password: ' + password),
+ },
],
- 'secure-text'
+ 'secure-text',
);
```
@@ -120,9 +120,9 @@ Example with the default button and a custom callback:
AlertIOS.prompt(
'Update username',
null,
- (text) => console.log('Your username is ' + text),
+ text => console.log('Your username is ' + text),
null,
- 'default'
+ 'default',
);
```
diff --git a/docs/animated.md b/docs/animated.md
index 0e278ac247c..6c114a18d5d 100644
--- a/docs/animated.md
+++ b/docs/animated.md
@@ -30,8 +30,15 @@ The following example contains a `View` which will fade in and fade out based on
```SnackPlayer name=Animated
-import React, { useRef } from "react";
-import { Animated, Text, View, StyleSheet, Button, SafeAreaView } from "react-native";
+import React, {useRef} from 'react';
+import {
+ Animated,
+ Text,
+ View,
+ StyleSheet,
+ Button,
+ SafeAreaView,
+} from 'react-native';
const App = () => {
// fadeAnim will be used as the value for opacity. Initial Value: 0
@@ -41,7 +48,8 @@ const App = () => {
// Will change fadeAnim value to 1 in 5 seconds
Animated.timing(fadeAnim, {
toValue: 1,
- duration: 5000
+ duration: 5000,
+ useNativeDriver: true,
}).start();
};
@@ -49,7 +57,8 @@ const App = () => {
// Will change fadeAnim value to 0 in 3 seconds
Animated.timing(fadeAnim, {
toValue: 0,
- duration: 3000
+ duration: 3000,
+ useNativeDriver: true,
}).start();
};
@@ -60,10 +69,9 @@ const App = () => {
styles.fadingContainer,
{
// Bind opacity to animated value
- opacity: fadeAnim
- }
- ]}
- >
+ opacity: fadeAnim,
+ },
+ ]}>
Fading View!
@@ -72,26 +80,26 @@ const App = () => {
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
fadingContainer: {
padding: 20,
- backgroundColor: "powderblue"
+ backgroundColor: 'powderblue',
},
fadingText: {
- fontSize: 28
+ fontSize: 28,
},
buttonRow: {
flexBasis: 100,
- justifyContent: "space-evenly",
- marginVertical: 16
- }
+ justifyContent: 'space-evenly',
+ marginVertical: 16,
+ },
});
export default App;
@@ -101,20 +109,28 @@ export default App;
```SnackPlayer name=Animated
-import React, { Component } from "react";
-import { Animated, Text, View, StyleSheet, Button, SafeAreaView } from "react-native";
+import React, {Component} from 'react';
+import {
+ Animated,
+ Text,
+ View,
+ StyleSheet,
+ Button,
+ SafeAreaView,
+} from 'react-native';
class App extends Component {
// fadeAnim will be used as the value for opacity. Initial Value: 0
state = {
- fadeAnim: new Animated.Value(0)
+ fadeAnim: new Animated.Value(0),
};
fadeIn = () => {
// Will change fadeAnim value to 1 in 5 seconds
Animated.timing(this.state.fadeAnim, {
toValue: 1,
- duration: 5000
+ duration: 5000,
+ useNativeDriver: true,
}).start();
};
@@ -122,7 +138,8 @@ class App extends Component {
// Will change fadeAnim value to 0 in 3 seconds
Animated.timing(this.state.fadeAnim, {
toValue: 0,
- duration: 3000
+ duration: 3000,
+ useNativeDriver: true,
}).start();
};
@@ -134,10 +151,9 @@ class App extends Component {
styles.fadingContainer,
{
// Bind opacity to animated value
- opacity: this.state.fadeAnim
- }
- ]}
- >
+ opacity: this.state.fadeAnim,
+ },
+ ]}>
Fading View!
@@ -152,21 +168,21 @@ class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
fadingContainer: {
padding: 20,
- backgroundColor: "powderblue"
+ backgroundColor: 'powderblue',
},
fadingText: {
- fontSize: 28
+ fontSize: 28,
},
buttonRow: {
flexBasis: 100,
- justifyContent: "space-evenly",
- marginVertical: 16
- }
+ justifyContent: 'space-evenly',
+ marginVertical: 16,
+ },
});
export default App;
@@ -200,8 +216,8 @@ In most cases, you will be using `timing()`. By default, it uses a symmetric eas
Animations are started by calling `start()` on your animation. `start()` takes a completion callback that will be called when the animation is done. If the animation finished running normally, the completion callback will be invoked with `{finished: true}`. If the animation is done because `stop()` was called on it before it could finish (e.g. because it was interrupted by a gesture or another animation), then it will receive `{finished: false}`.
-```jsx
-Animated.timing({}).start(({ finished }) => {
+```tsx
+Animated.timing({}).start(({finished}) => {
/* completion callback */
});
```
@@ -266,10 +282,10 @@ Gestures, like panning or scrolling, and other events can map directly to animat
For example, when working with horizontal scrolling gestures, you would do the following in order to map `event.nativeEvent.contentOffset.x` to `scrollX` (an `Animated.Value`):
-```jsx
+```tsx
onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
- [{ nativeEvent: {
+ [{nativeEvent: {
contentOffset: {
x: scrollX
}
@@ -288,8 +304,8 @@ When the given value is a ValueXY instead of a Value, each config option may be
### `decay()`
-```jsx
-static decay(value, config)
+```tsx
+static decay(value, config): CompositeAnimation;
```
Animates a value from an initial velocity to zero based on a decay coefficient.
@@ -299,14 +315,14 @@ Config is an object that may have the following options:
- `velocity`: Initial velocity. Required.
- `deceleration`: Rate of decay. Default 0.997.
- `isInteraction`: Whether or not this animation creates an "interaction handle" on the `InteractionManager`. Default true.
-- `useNativeDriver`: Uses the native driver when true. Default false.
+- `useNativeDriver`: Uses the native driver when true. Required.
---
### `timing()`
-```jsx
-static timing(value, config)
+```tsx
+static timing(value, config): CompositeAnimation;
```
Animates a value along a timed easing curve. The [`Easing`](easing) module has tons of predefined curves, or you can use your own function.
@@ -317,14 +333,14 @@ Config is an object that may have the following options:
- `easing`: Easing function to define curve. Default is `Easing.inOut(Easing.ease)`.
- `delay`: Start the animation after delay (milliseconds). Default 0.
- `isInteraction`: Whether or not this animation creates an "interaction handle" on the `InteractionManager`. Default true.
-- `useNativeDriver`: Uses the native driver when true. Default false.
+- `useNativeDriver`: Uses the native driver when true. Required.
---
### `spring()`
-```jsx
-static spring(value, config)
+```tsx
+static spring(value, config): CompositeAnimation;
```
Animates a value according to an analytical spring model based on [damped harmonic oscillation](https://en.wikipedia.org/wiki/Harmonic_oscillator#Damped_harmonic_oscillator). Tracks velocity state to create fluid motions as the `toValue` updates, and can be chained together.
@@ -354,14 +370,14 @@ Other configuration options are as follows:
- `restSpeedThreshold`: The speed at which the spring should be considered at rest in pixels per second. Default 0.001.
- `delay`: Start the animation after delay (milliseconds). Default 0.
- `isInteraction`: Whether or not this animation creates an "interaction handle" on the `InteractionManager`. Default true.
-- `useNativeDriver`: Uses the native driver when true. Default false.
+- `useNativeDriver`: Uses the native driver when true. Required.
---
### `add()`
-```jsx
-static add(a, b)
+```tsx
+static add(a: Animated, b: Animated): AnimatedAddition;
```
Creates a new Animated value composed from two Animated values added together.
@@ -370,8 +386,8 @@ Creates a new Animated value composed from two Animated values added together.
### `subtract()`
-```jsx
-static subtract(a, b)
+```tsx
+static subtract(a: Animated, b: Animated): AnimatedSubtraction;
```
Creates a new Animated value composed by subtracting the second Animated value from the first Animated value.
@@ -380,8 +396,8 @@ Creates a new Animated value composed by subtracting the second Animated value f
### `divide()`
-```jsx
-static divide(a, b)
+```tsx
+static divide(a: Animated, b: Animated): AnimatedDivision;
```
Creates a new Animated value composed by dividing the first Animated value by the second Animated value.
@@ -390,8 +406,8 @@ Creates a new Animated value composed by dividing the first Animated value by th
### `multiply()`
-```jsx
-static multiply(a, b)
+```tsx
+static multiply(a: Animated, b: Animated): AnimatedMultiplication;
```
Creates a new Animated value composed from two Animated values multiplied together.
@@ -400,8 +416,8 @@ Creates a new Animated value composed from two Animated values multiplied togeth
### `modulo()`
-```jsx
-static modulo(a, modulus)
+```tsx
+static modulo(a: Animated, modulus: number): AnimatedModulo;
```
Creates a new Animated value that is the (non-negative) modulo of the provided Animated value
@@ -410,8 +426,8 @@ Creates a new Animated value that is the (non-negative) modulo of the provided A
### `diffClamp()`
-```jsx
-static diffClamp(a, min, max)
+```tsx
+static diffClamp(a: Animated, min: number, max: number): AnimatedDiffClamp;
```
Create a new Animated value that is limited between 2 values. It uses the difference between the last value so even if the value is far from the bounds it will start changing when the value starts getting closer again. (`value = clamp(value + diff, min, max)`).
@@ -422,8 +438,8 @@ This is useful with scroll events, for example, to show the navbar when scrollin
### `delay()`
-```jsx
-static delay(time)
+```tsx
+static delay(time: number): CompositeAnimation;
```
Starts an animation after the given delay.
@@ -432,8 +448,8 @@ Starts an animation after the given delay.
### `sequence()`
-```jsx
-static sequence(animations)
+```tsx
+static sequence(animations: CompositeAnimation[]): CompositeAnimation;
```
Starts an array of animations in order, waiting for each to complete before starting the next. If the current running animation is stopped, no following animations will be started.
@@ -442,8 +458,11 @@ Starts an array of animations in order, waiting for each to complete before star
### `parallel()`
-```jsx
-static parallel(animations, config?)
+```tsx
+static parallel(
+ animations: CompositeAnimation[],
+ config?: ParallelConfig
+): CompositeAnimation;
```
Starts an array of animations all at the same time. By default, if one of the animations is stopped, they will all be stopped. You can override this with the `stopTogether` flag.
@@ -452,8 +471,11 @@ Starts an array of animations all at the same time. By default, if one of the an
### `stagger()`
-```jsx
-static stagger(time, animations)
+```tsx
+static stagger(
+ time: number,
+ animations: CompositeAnimation[]
+): CompositeAnimation;
```
Array of animations may run in parallel (overlap), but are started in sequence with successive delays. Nice for doing trailing effects.
@@ -462,8 +484,11 @@ Array of animations may run in parallel (overlap), but are started in sequence w
### `loop()`
-```jsx
-static loop(animation, config?)
+```tsx
+static loop(
+ animation: CompositeAnimation[],
+ config?: LoopAnimationConfig
+): CompositeAnimation;
```
Loops a given animation continuously, so that each time it reaches the end, it resets and begins again from the start. Will loop without blocking the JS thread if the child animation is set to `useNativeDriver: true`. In addition, loops can prevent `VirtualizedList`-based components from rendering more rows while the animation is running. You can pass `isInteraction: false` in the child animation config to fix this.
@@ -476,36 +501,46 @@ Config is an object that may have the following options:
### `event()`
-```jsx
-static event(argMapping, config?)
+```tsx
+static event(
+ argMapping: Mapping[],
+ config?: EventConfig
+): (...args: any[]) => void;
```
Takes an array of mappings and extracts values from each arg accordingly, then calls `setValue` on the mapped outputs. e.g.
-```jsx
- onScroll={Animated.event(
- [{nativeEvent: {contentOffset: {x: this._scrollX}}}],
- {listener: (event) => console.log(event)}, // Optional async listener
- )}
+```tsx
+onScroll={Animated.event(
+ [{nativeEvent: {contentOffset: {x: this._scrollX}}}],
+ {listener: (event: ScrollEvent) => console.log(event)}, // Optional async listener
+)}
...
- onPanResponderMove: Animated.event([
- null, // raw event arg ignored
- {dx: this._panX}], // gestureState arg
-{listener: (event, gestureState) => console.log(event, gestureState)}, // Optional async listener
- ),
+onPanResponderMove: Animated.event(
+ [
+ null, // raw event arg ignored
+ {dx: this._panX},
+ ], // gestureState arg
+ {
+ listener: (
+ event: GestureResponderEvent,
+ gestureState: PanResponderGestureState
+ ) => console.log(event, gestureState),
+ } // Optional async listener
+);
```
Config is an object that may have the following options:
- `listener`: Optional async listener.
-- `useNativeDriver`: Uses the native driver when true. Default false.
+- `useNativeDriver`: Uses the native driver when true. Required.
---
### `forkEvent()`
```jsx
-static forkEvent(event, listener)
+static forkEvent(event: AnimatedEvent, listener: Function): AnimatedEvent;
```
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.
@@ -515,29 +550,29 @@ Advanced imperative API for snooping on animated events that are passed in throu
### `unforkEvent()`
```jsx
-static unforkEvent(event, listener)
+static unforkEvent(event: AnimatedEvent, listener: Function);
```
---
### `start()`
-```jsx
-static start([callback]: ?(result?: {finished: boolean}) => void)
+```tsx
+static start(callback?: (result: {finished: boolean}) => void);
```
Animations are started by calling start() on your animation. start() takes a completion callback that will be called when the animation is done or when the animation is done because stop() was called on it before it could finish.
**Parameters:**
-| Name | Type | Required | Description |
-| -------- | ------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| callback | ?(result?: {finished: boolean}) | No | Function that will be called after the animation finished running normally or when the animation is done because stop() was called on it before it could finish |
+| Name | Type | Required | Description |
+| -------- | ------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| callback | (result: {finished: boolean}) => void | No | Function that will be called after the animation finished running normally or when the animation is done because stop() was called on it before it could finish |
Start example with callback:
-```jsx
-Animated.timing({}).start(({ finished }) => {
+```tsx
+Animated.timing({}).start(({finished}) => {
/* completion callback */
});
```
@@ -546,8 +581,8 @@ Animated.timing({}).start(({ finished }) => {
### `stop()`
-```jsx
-static stop()
+```tsx
+static stop();
```
Stops any running animation.
@@ -556,8 +591,8 @@ Stops any running animation.
### `reset()`
-```jsx
-static reset()
+```tsx
+static reset();
```
Stops any running animation and resets the value to its original.
diff --git a/docs/animatedvalue.md b/docs/animatedvalue.md
index 36b782c777c..f6caa7ba422 100644
--- a/docs/animatedvalue.md
+++ b/docs/animatedvalue.md
@@ -15,8 +15,8 @@ Typically initialized with `new Animated.Value(0);`
### `setValue()`
-```jsx
-setValue(value);
+```tsx
+setValue(value: number);
```
Directly set the value. This will stop any animations running on the value and update all the bound properties.
@@ -31,8 +31,8 @@ Directly set the value. This will stop any animations running on the value and u
### `setOffset()`
-```jsx
-setOffset(offset);
+```tsx
+setOffset(offset: number);
```
Sets an offset that is applied on top of whatever value is set, whether via `setValue`, an animation, or `Animated.event`. Useful for compensating things like the start of a pan gesture.
@@ -47,7 +47,7 @@ Sets an offset that is applied on top of whatever value is set, whether via `set
### `flattenOffset()`
-```jsx
+```tsx
flattenOffset();
```
@@ -57,7 +57,7 @@ Merges the offset value into the base value and resets the offset to zero. The f
### `extractOffset()`
-```jsx
+```tsx
extractOffset();
```
@@ -67,8 +67,8 @@ Sets the offset value to the base value, and resets the base value to zero. The
### `addListener()`
-```jsx
-addListener(callback);
+```tsx
+addListener(callback: (state: {value: number}) => void): string;
```
Adds an asynchronous listener to the value so you can observe updates from animations. This is useful because there is no way to synchronously read the value because it might be driven natively.
@@ -85,8 +85,8 @@ Returns a string that serves as an identifier for the listener.
### `removeListener()`
-```jsx
-removeListener(id);
+```tsx
+removeListener(id: string);
```
Unregister a listener. The `id` param shall match the identifier previously returned by `addListener()`.
@@ -101,7 +101,7 @@ Unregister a listener. The `id` param shall match the identifier previously retu
### `removeAllListeners()`
-```jsx
+```tsx
removeAllListeners();
```
@@ -111,8 +111,8 @@ Remove all registered listeners.
### `stopAnimation()`
-```jsx
-stopAnimation([callback]);
+```tsx
+stopAnimation(callback?: (value: number) => void);
```
Stops any running animation or tracking. `callback` is invoked with the final value after stopping the animation, which is useful for updating state to match the animation position with layout.
@@ -127,8 +127,8 @@ Stops any running animation or tracking. `callback` is invoked with the final va
### `resetAnimation()`
-```jsx
-resetAnimation([callback]);
+```tsx
+resetAnimation(callback?: (value: number) => void);
```
Stops any animation and resets the value to its original.
@@ -143,8 +143,8 @@ Stops any animation and resets the value to its original.
### `interpolate()`
-```jsx
-interpolate(config);
+```tsx
+interpolate(config: InterpolationConfigType);
```
Interpolates the value before updating the property, e.g. mapping 0-1 to 0-10.
@@ -170,7 +170,7 @@ The `config` object is composed of the following keys:
### `animate()`
-```jsx
+```tsx
animate(animation, callback);
```
@@ -182,29 +182,3 @@ Typically only used internally, but could be used by a custom Animation class.
| --------- | --------- | -------- | ------------------- |
| animation | Animation | Yes | See `Animation.js`. |
| callback | function | Yes | Callback function. |
-
----
-
-### `stopTracking()`
-
-```jsx
-stopTracking();
-```
-
-Typically only used internally.
-
----
-
-### `track()`
-
-```jsx
-track(tracking);
-```
-
-Typically only used internally.
-
-**Parameters:**
-
-| Name | Type | Required | Description |
-| -------- | ------------ | -------- | --------------------- |
-| tracking | AnimatedNode | Yes | See `AnimatedNode.js` |
diff --git a/docs/animatedvaluexy.md b/docs/animatedvaluexy.md
index cfe73bc5a59..e4d29cce1a0 100644
--- a/docs/animatedvaluexy.md
+++ b/docs/animatedvaluexy.md
@@ -8,8 +8,8 @@ title: Animated.ValueXY
## Example
```SnackPlayer name=Animated.ValueXY
-import React, { useRef } from "react";
-import { Animated, PanResponder, StyleSheet, View } from "react-native";
+import React, {useRef} from 'react';
+import {Animated, PanResponder, StyleSheet, View} from 'react-native';
const DraggableView = () => {
const pan = useRef(new Animated.ValueXY()).current;
@@ -26,7 +26,7 @@ const DraggableView = () => {
onPanResponderRelease: () => {
Animated.spring(
pan, // Auto-multiplexed
- { toValue: { x: 0, y: 0 } } // Back to zero
+ {toValue: {x: 0, y: 0}, useNativeDriver: true}, // Back to zero
).start();
},
});
@@ -44,11 +44,11 @@ const DraggableView = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center",
- alignItems: "center",
+ justifyContent: 'center',
+ alignItems: 'center',
},
box: {
- backgroundColor: "#61dafb",
+ backgroundColor: '#61dafb',
width: 80,
height: 80,
borderRadius: 4,
@@ -66,39 +66,39 @@ export default DraggableView;
### `setValue()`
-```jsx
-setValue(value);
+```tsx
+setValue(value: {x: number; y: number});
```
Directly set the value. This will stop any animations running on the value and update all the bound properties.
**Parameters:**
-| Name | Type | Required | Description |
-| ----- | ------ | -------- | ----------- |
-| value | number | Yes | Value |
+| Name | Type | Required | Description |
+| ----- | ---------------------- | -------- | ----------- |
+| value | {x: number; y: number} | Yes | Value |
---
### `setOffset()`
-```jsx
-setOffset(offset);
+```tsx
+setOffset(offset: {x: number; y: number});
```
Sets an offset that is applied on top of whatever value is set, whether via `setValue`, an animation, or `Animated.event`. Useful for compensating things like the start of a pan gesture.
**Parameters:**
-| Name | Type | Required | Description |
-| ------ | ------ | -------- | ------------ |
-| offset | number | Yes | Offset value |
+| Name | Type | Required | Description |
+| ------ | ---------------------- | -------- | ------------ |
+| offset | {x: number; y: number} | Yes | Offset value |
---
### `flattenOffset()`
-```jsx
+```tsx
flattenOffset();
```
@@ -108,7 +108,7 @@ Merges the offset value into the base value and resets the offset to zero. The f
### `extractOffset()`
-```jsx
+```tsx
extractOffset();
```
@@ -118,8 +118,8 @@ Sets the offset value to the base value, and resets the base value to zero. The
### `addListener()`
-```jsx
-addListener(callback);
+```tsx
+addListener(callback: (value: {x: number; y: number}) => void);
```
Adds an asynchronous listener to the value so you can observe updates from animations. This is useful because there is no way to synchronously read the value because it might be driven natively.
@@ -136,8 +136,8 @@ Returns a string that serves as an identifier for the listener.
### `removeListener()`
-```jsx
-removeListener(id);
+```tsx
+removeListener(id: string);
```
Unregister a listener. The `id` param shall match the identifier previously returned by `addListener()`.
@@ -152,7 +152,7 @@ Unregister a listener. The `id` param shall match the identifier previously retu
### `removeAllListeners()`
-```jsx
+```tsx
removeAllListeners();
```
@@ -162,8 +162,8 @@ Remove all registered listeners.
### `stopAnimation()`
-```jsx
-stopAnimation([callback]);
+```tsx
+stopAnimation(callback?: (value: {x: number; y: number}) => void);
```
Stops any running animation or tracking. `callback` is invoked with the final value after stopping the animation, which is useful for updating state to match the animation position with layout.
@@ -178,8 +178,8 @@ Stops any running animation or tracking. `callback` is invoked with the final va
### `resetAnimation()`
-```jsx
-resetAnimation([callback]);
+```tsx
+resetAnimation(callback?: (value: {x: number; y: number}) => void);
```
Stops any animation and resets the value to its original.
@@ -194,13 +194,13 @@ Stops any animation and resets the value to its original.
### `getLayout()`
-```jsx
-getLayout();
+```tsx
+getLayout(): {left: Animated.Value, top: Animated.Value};
```
Converts `{x, y}` into `{left, top}` for use in style, e.g.
-```jsx
+```tsx
style={this.state.anim.getLayout()}
```
@@ -208,13 +208,16 @@ style={this.state.anim.getLayout()}
### `getTranslateTransform()`
-```jsx
-getTranslateTransform();
+```tsx
+getTranslateTransform(): [
+ {translateX: Animated.Value},
+ {translateY: Animated.Value},
+];
```
Converts `{x, y}` into a useable translation transform, e.g.
-```jsx
+```tsx
style={{
transform: this.state.anim.getTranslateTransform()
}}
diff --git a/docs/animations.md b/docs/animations.md
index 18704441310..5218ceae425 100644
--- a/docs/animations.md
+++ b/docs/animations.md
@@ -17,47 +17,119 @@ The [`Animated`](animated) API is designed to concisely express a wide variety o
For example, a container view that fades in when it is mounted may look like this:
-```SnackPlayer
-import React, { useRef, useEffect } from 'react';
-import { Animated, Text, View } from 'react-native';
+
+
-const FadeInView = (props) => {
- const fadeAnim = useRef(new Animated.Value(0)).current // Initial value for opacity: 0
+```SnackPlayer ext=js
+import React, {useRef, useEffect} from 'react';
+import {Animated, Text, View} from 'react-native';
+
+const FadeInView = props => {
+ const fadeAnim = useRef(new Animated.Value(0)).current; // Initial value for opacity: 0
useEffect(() => {
- Animated.timing(
- fadeAnim,
- {
- toValue: 1,
- duration: 10000,
- }
- ).start();
- }, [fadeAnim])
+ Animated.timing(fadeAnim, {
+ toValue: 1,
+ duration: 10000,
+ useNativeDriver: true,
+ }).start();
+ }, [fadeAnim]);
return (
-
+ opacity: fadeAnim, // Bind opacity to animated value
+ }}>
{props.children}
);
-}
+};
// You can then use your `FadeInView` in place of a `View` in your components:
export default () => {
return (
-
-
- Fading in
+
+
+
+ Fading in
+
- )
-}
+ );
+};
+```
+
+
+
+
+```SnackPlayer ext=tsx
+import React, {useRef, useEffect} from 'react';
+import {Animated, Text, View} from 'react-native';
+import type {PropsWithChildren} from 'react';
+import type {ViewStyle} from 'react-native';
+
+type FadeInViewProps = PropsWithChildren<{style: ViewStyle}>;
+
+const FadeInView: React.FC = props => {
+ const fadeAnim = useRef(new Animated.Value(0)).current; // Initial value for opacity: 0
+
+ useEffect(() => {
+ Animated.timing(fadeAnim, {
+ toValue: 1,
+ duration: 10000,
+ useNativeDriver: true,
+ }).start();
+ }, [fadeAnim]);
+
+ return (
+
+ {props.children}
+
+ );
+};
+
+// You can then use your `FadeInView` in place of a `View` in your components:
+export default () => {
+ return (
+
+
+
+ Fading in
+
+
+
+ );
+};
```
+
+
+
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, only the opacity) on each frame as the value animates to the final value of 1.
@@ -74,11 +146,12 @@ By default, `timing` will use an easeInOut curve that conveys gradual accelerati
For example, if we want to create a 2-second long animation of an object that slightly backs up before moving to its final position:
-```jsx
+```tsx
Animated.timing(this.state.xPosition, {
toValue: 100,
easing: Easing.back(),
- duration: 2000
+ duration: 2000,
+ useNativeDriver: true,
}).start();
```
@@ -90,24 +163,27 @@ Animations can be combined and played in sequence or in parallel. Sequential ani
For example, the following animation coasts to a stop, then it springs back while twirling in parallel:
-```jsx
+```tsx
Animated.sequence([
// decay, then spring to start and twirl
Animated.decay(position, {
// coast to a stop
- velocity: { x: gestureState.vx, y: gestureState.vy }, // velocity from gesture release
- deceleration: 0.997
+ velocity: {x: gestureState.vx, y: gestureState.vy}, // velocity from gesture release
+ deceleration: 0.997,
+ useNativeDriver: true,
}),
Animated.parallel([
// after decay, in parallel:
Animated.spring(position, {
- toValue: { x: 0, y: 0 } // return to start
+ toValue: {x: 0, y: 0}, // return to start
+ useNativeDriver: true,
}),
Animated.timing(twirl, {
// and twirl
- toValue: 360
- })
- ])
+ toValue: 360,
+ useNativeDriver: true,
+ }),
+ ]),
]).start(); // start the sequence group
```
@@ -121,12 +197,13 @@ You can [combine two animated values](animated#combining-animated-values) via ad
There are some cases where an animated value needs to invert another animated value for calculation. An example is inverting a scale (2x --> 0.5x):
-```jsx
+```tsx
const a = new Animated.Value(1);
const b = Animated.divide(1, a);
Animated.spring(a, {
- toValue: 2
+ toValue: 2,
+ useNativeDriver: true,
}).start();
```
@@ -136,16 +213,16 @@ Each property can be run through an interpolation first. An interpolation maps i
A basic mapping to convert a 0-1 range to a 0-100 range would be:
-```jsx
+```tsx
value.interpolate({
inputRange: [0, 1],
- outputRange: [0, 100]
+ outputRange: [0, 100],
});
```
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
+```tsx
style={{
opacity: this.state.fadeAnim, // Binds directly
transform: [{
@@ -159,10 +236,10 @@ For example, you may want to think about your `Animated.Value` as going from 0 t
[`interpolate()`](animated#interpolate) supports multiple range segments as well, which is handy for defining dead zones and other handy tricks. For example, to get a negation relationship at -300 that goes to 0 at -100, then back up to 1 at 0, and then back down to zero at 100 followed by a dead-zone that remains at 0 for everything beyond that, you could do:
-```jsx
+```tsx
value.interpolate({
inputRange: [-300, -100, 0, 100, 101],
- outputRange: [300, 0, 1, 0, 0]
+ outputRange: [300, 0, 1, 0, 0],
});
```
@@ -185,10 +262,10 @@ Input | Output
`interpolate()` also supports mapping to strings, allowing you to animate colors as well as values with units. For example, if you wanted to animate a rotation you could do:
-```jsx
+```tsx
value.interpolate({
inputRange: [0, 360],
- outputRange: ['0deg', '360deg']
+ outputRange: ['0deg', '360deg'],
});
```
@@ -198,13 +275,14 @@ value.interpolate({
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();
+```tsx
+Animated.spring(follower, {toValue: leader}).start();
Animated.timing(opacity, {
toValue: pan.x.interpolate({
inputRange: [0, 300],
- outputRange: [1, 0]
- })
+ outputRange: [1, 0],
+ useNativeDriver: true,
+ }),
}).start();
```
@@ -216,10 +294,10 @@ Gestures, like panning or scrolling, and other events can map directly to animat
For example, when working with horizontal scrolling gestures, you would do the following in order to map `event.nativeEvent.contentOffset.x` to `scrollX` (an `Animated.Value`):
-```jsx
+```tsx
onScroll={Animated.event(
// scrollX = e.nativeEvent.contentOffset.x
- [{ nativeEvent: {
+ [{nativeEvent: {
contentOffset: {
x: scrollX
}
@@ -236,7 +314,7 @@ The following example implements a horizontal scrolling carousel where the scrol
```SnackPlayer name=Animated&supportedPlatforms=ios,android
-import React, { useRef } from "react";
+import React, {useRef} from 'react';
import {
SafeAreaView,
ScrollView,
@@ -245,15 +323,17 @@ import {
View,
ImageBackground,
Animated,
- useWindowDimensions
-} from "react-native";
+ useWindowDimensions,
+} from 'react-native';
-const images = new Array(6).fill('https://images.unsplash.com/photo-1556740749-887f6717d7e4');
+const images = new Array(6).fill(
+ 'https://images.unsplash.com/photo-1556740749-887f6717d7e4',
+);
const App = () => {
const scrollX = useRef(new Animated.Value(0)).current;
- const { width: windowWidth } = useWindowDimensions();
+ const {width: windowWidth} = useWindowDimensions();
return (
@@ -266,23 +346,19 @@ const App = () => {
{
nativeEvent: {
contentOffset: {
- x: scrollX
- }
- }
- }
+ x: scrollX,
+ },
+ },
+ },
])}
- scrollEventThrottle={1}
- >
+ scrollEventThrottle={1}>
{images.map((image, imageIndex) => {
return (
-
-
+
+
- {"Image - " + imageIndex}
+ {'Image - ' + imageIndex}
@@ -296,15 +372,15 @@ const App = () => {
inputRange: [
windowWidth * (imageIndex - 1),
windowWidth * imageIndex,
- windowWidth * (imageIndex + 1)
+ windowWidth * (imageIndex + 1),
],
outputRange: [8, 16, 8],
- extrapolate: "clamp"
+ extrapolate: 'clamp',
});
return (
);
})}
@@ -312,51 +388,51 @@ const App = () => {
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
scrollContainer: {
height: 300,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
card: {
flex: 1,
marginVertical: 4,
marginHorizontal: 16,
borderRadius: 5,
- overflow: "hidden",
- alignItems: "center",
- justifyContent: "center"
+ overflow: 'hidden',
+ alignItems: 'center',
+ justifyContent: 'center',
},
textContainer: {
- backgroundColor: "rgba(0,0,0, 0.7)",
+ backgroundColor: 'rgba(0,0,0, 0.7)',
paddingHorizontal: 24,
paddingVertical: 8,
- borderRadius: 5
+ borderRadius: 5,
},
infoText: {
- color: "white",
+ color: 'white',
fontSize: 16,
- fontWeight: "bold"
+ fontWeight: 'bold',
},
normalDot: {
height: 8,
width: 8,
borderRadius: 4,
- backgroundColor: "silver",
- marginHorizontal: 4
+ backgroundColor: 'silver',
+ marginHorizontal: 4,
},
indicatorContainer: {
- flexDirection: "row",
- alignItems: "center",
- justifyContent: "center"
- }
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
});
export default App;
@@ -365,8 +441,11 @@ export default App;
-```SnackPlayer name=Animated&supportedPlatforms=ios,android
-import React, { Component } from "react";
+
+
+
+```SnackPlayer name=Animated&supportedPlatforms=ios,android&ext=js
+import React, {Component} from 'react';
import {
SafeAreaView,
ScrollView,
@@ -375,32 +454,37 @@ import {
View,
ImageBackground,
Animated,
- Dimensions
-} from "react-native";
+ Dimensions,
+} from 'react-native';
-const images = new Array(6).fill('https://images.unsplash.com/photo-1556740749-887f6717d7e4');
+const images = new Array(6).fill(
+ 'https://images.unsplash.com/photo-1556740749-887f6717d7e4',
+);
-const window = Dimensions.get("window");
+const windowDimensions = Dimensions.get('window');
export default class App extends Component {
scrollX = new Animated.Value(0);
state = {
dimensions: {
- window
- }
+ window: windowDimensions,
+ },
};
- onDimensionsChange = ({ window }) => {
- this.setState({ dimensions: { window } });
+ onDimensionsChange = ({window}) => {
+ this.setState({dimensions: {window}});
};
componentDidMount() {
- Dimensions.addEventListener("change", this.onDimensionsChange);
+ this.dimensionsSubscription = Dimensions.addEventListener(
+ 'change',
+ this.onDimensionsChange,
+ );
}
componentWillUnmount() {
- Dimensions.removeEventListener("change", this.onDimensionsChange);
+ this.dimensionsSubscription.remove();
}
render() {
@@ -417,26 +501,24 @@ export default class App extends Component {
{
nativeEvent: {
contentOffset: {
- x: this.scrollX
- }
- }
- }
+ x: this.scrollX,
+ },
+ },
+ },
])}
- scrollEventThrottle={1}
- >
+ scrollEventThrottle={1}>
{images.map((image, imageIndex) => {
return (
-
+ key={imageIndex}>
+
- {"Image - " + imageIndex}
+ {'Image - ' + imageIndex}
@@ -450,15 +532,15 @@ export default class App extends Component {
inputRange: [
windowWidth * (imageIndex - 1),
windowWidth * imageIndex,
- windowWidth * (imageIndex + 1)
+ windowWidth * (imageIndex + 1),
],
outputRange: [8, 16, 8],
- extrapolate: "clamp"
+ extrapolate: 'clamp',
});
return (
);
})}
@@ -472,55 +554,216 @@ export default class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
scrollContainer: {
height: 300,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
card: {
flex: 1,
marginVertical: 4,
marginHorizontal: 16,
borderRadius: 5,
- overflow: "hidden",
- alignItems: "center",
- justifyContent: "center"
+ overflow: 'hidden',
+ alignItems: 'center',
+ justifyContent: 'center',
},
textContainer: {
- backgroundColor: "rgba(0,0,0, 0.7)",
+ backgroundColor: 'rgba(0,0,0, 0.7)',
paddingHorizontal: 24,
paddingVertical: 8,
- borderRadius: 5
+ borderRadius: 5,
},
infoText: {
- color: "white",
+ color: 'white',
fontSize: 16,
- fontWeight: "bold"
+ fontWeight: 'bold',
},
normalDot: {
height: 8,
width: 8,
borderRadius: 4,
- backgroundColor: "silver",
- marginHorizontal: 4
+ backgroundColor: 'silver',
+ marginHorizontal: 4,
},
indicatorContainer: {
- flexDirection: "row",
- alignItems: "center",
- justifyContent: "center"
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
+```
+
+
+
+
+```SnackPlayer name=Animated&supportedPlatforms=ios,android&ext=tsx
+import React, {Component} from 'react';
+import {
+ SafeAreaView,
+ ScrollView,
+ Text,
+ StyleSheet,
+ View,
+ ImageBackground,
+ Animated,
+ Dimensions,
+} from 'react-native';
+import type {ScaledSize, EmitterSubscription} from 'react-native';
+
+const images = new Array(6).fill(
+ 'https://images.unsplash.com/photo-1556740749-887f6717d7e4',
+);
+
+const windowDimensions = Dimensions.get('window');
+
+export default class App extends Component {
+ dimensionsSubscription?: EmitterSubscription;
+ scrollX = new Animated.Value(0);
+
+ state = {
+ dimensions: {
+ window: windowDimensions,
+ },
+ };
+
+ onDimensionsChange = ({window}: {window: ScaledSize}) => {
+ this.setState({dimensions: {window}});
+ };
+
+ componentDidMount() {
+ this.dimensionsSubscription = Dimensions.addEventListener(
+ 'change',
+ this.onDimensionsChange,
+ );
+ }
+
+ componentWillUnmount() {
+ this.dimensionsSubscription?.remove();
+ }
+
+ render() {
+ const windowWidth = this.state.dimensions.window.width;
+
+ return (
+
+
+
+ {images.map((image, imageIndex) => {
+ return (
+
+
+
+
+ {'Image - ' + imageIndex}
+
+
+
+
+ );
+ })}
+
+
+ {images.map((image, imageIndex) => {
+ const width = this.scrollX.interpolate({
+ inputRange: [
+ windowWidth * (imageIndex - 1),
+ windowWidth * imageIndex,
+ windowWidth * (imageIndex + 1),
+ ],
+ outputRange: [8, 16, 8],
+ extrapolate: 'clamp',
+ });
+ return (
+
+ );
+ })}
+
+
+
+ );
}
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ scrollContainer: {
+ height: 300,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ card: {
+ flex: 1,
+ marginVertical: 4,
+ marginHorizontal: 16,
+ borderRadius: 5,
+ overflow: 'hidden',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ textContainer: {
+ backgroundColor: 'rgba(0,0,0, 0.7)',
+ paddingHorizontal: 24,
+ paddingVertical: 8,
+ borderRadius: 5,
+ },
+ infoText: {
+ color: 'white',
+ fontSize: 16,
+ fontWeight: 'bold',
+ },
+ normalDot: {
+ height: 8,
+ width: 8,
+ borderRadius: 4,
+ backgroundColor: 'silver',
+ marginHorizontal: 4,
+ },
+ indicatorContainer: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
});
```
+
+
+
When using `PanResponder`, you could use the following code to extract the x and y positions from `gestureState.dx` and `gestureState.dy`. We use a `null` in the first position of the array, as we are only interested in the second argument passed to the `PanResponder` handler, which is the `gestureState`.
-```jsx
+```tsx
onPanResponderMove={Animated.event(
[null, // ignore the native event
// extract dx and dy from gestureState
@@ -535,22 +778,22 @@ onPanResponderMove={Animated.event(
```SnackPlayer name=Animated
-import React, { useRef } from "react";
-import { Animated, View, StyleSheet, PanResponder, Text } from "react-native";
+import React, {useRef} from 'react';
+import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native';
const App = () => {
const pan = useRef(new Animated.ValueXY()).current;
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: () => true,
- onPanResponderMove: Animated.event([
- null,
- { dx: pan.x, dy: pan.y }
- ]),
+ onPanResponderMove: Animated.event([null, {dx: pan.x, dy: pan.y}]),
onPanResponderRelease: () => {
- Animated.spring(pan, { toValue: { x: 0, y: 0 } }).start();
- }
- })
+ Animated.spring(pan, {
+ toValue: {x: 0, y: 0},
+ useNativeDriver: true,
+ }).start();
+ },
+ }),
).current;
return (
@@ -558,33 +801,32 @@ const App = () => {
Drag & Release this box!
+ {...panResponder.panHandlers}>
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
titleText: {
fontSize: 14,
lineHeight: 24,
- fontWeight: "bold"
+ fontWeight: 'bold',
},
box: {
height: 150,
width: 150,
- backgroundColor: "blue",
- borderRadius: 5
- }
+ backgroundColor: 'blue',
+ borderRadius: 5,
+ },
});
export default App;
@@ -594,8 +836,8 @@ export default App;
```SnackPlayer name=Animated
-import React, { Component } from "react";
-import { Animated, View, StyleSheet, PanResponder, Text } from "react-native";
+import React, {Component} from 'react';
+import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native';
export default class App extends Component {
pan = new Animated.ValueXY();
@@ -603,11 +845,14 @@ export default class App extends Component {
onMoveShouldSetPanResponder: () => true,
onPanResponderMove: Animated.event([
null,
- { dx: this.pan.x, dy: this.pan.y }
+ {dx: this.pan.x, dy: this.pan.y},
]),
onPanResponderRelease: () => {
- Animated.spring(this.pan, { toValue: { x: 0, y: 0 } }).start();
- }
+ Animated.spring(this.pan, {
+ toValue: {x: 0, y: 0},
+ useNativeDriver: true,
+ }).start();
+ },
});
render() {
@@ -616,10 +861,9 @@ export default class App extends Component {
Drag & Release this box!
+ {...this.panResponder.panHandlers}>
@@ -630,20 +874,20 @@ export default class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
titleText: {
fontSize: 14,
lineHeight: 24,
- fontWeight: "bold"
+ fontWeight: 'bold',
},
box: {
height: 150,
width: 150,
- backgroundColor: "blue",
- borderRadius: 5
- }
+ backgroundColor: 'blue',
+ borderRadius: 5,
+ },
});
```
@@ -663,13 +907,13 @@ You may notice that there is no clear way to read the current value while animat
The `Animated` API is designed to be serializable. By using the [native driver](/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 straightforward. You can add `useNativeDriver: true` to the animation config when starting it.
+Using the native driver for normal animations can be accomplished by setting `useNativeDriver: true` in animation config when starting it. Animations without a `useNativeDriver` property will default to false for legacy reasons, but emit a warning (and typechecking error in TypeScript).
-```jsx
+```tsx
Animated.timing(this.state.animatedValue, {
toValue: 1,
duration: 500,
- useNativeDriver: true // <-- Add this
+ useNativeDriver: true, // <-- Set this to true
}).start();
```
@@ -677,18 +921,18 @@ Animated values are only compatible with one driver so if you use native driver
The native driver also works with `Animated.event`. This is especially useful for animations that follow the scroll position as without the native driver, the animation will always run a frame behind the gesture due to the async nature of React Native.
-```jsx
+```tsx
{content}
@@ -706,14 +950,14 @@ When an animation is running, it can prevent `VirtualizedList` components from r
While using transform styles such as `rotateY`, `rotateX`, and others ensure the transform style `perspective` is in place. At this time some animations may not render on Android without it. Example below.
-```jsx
+```tsx
```
@@ -733,9 +977,8 @@ Note that although `LayoutAnimation` is very powerful and can be quite useful, i
Note that in order to get this to work on **Android** you need to set the following flags via `UIManager`:
-```jsx
-UIManager.setLayoutAnimationEnabledExperimental &&
- UIManager.setLayoutAnimationEnabledExperimental(true);
+```tsx
+UIManager.setLayoutAnimationEnabledExperimental(true);
```
```SnackPlayer name=LayoutAnimations&supportedPlatforms=ios,android
@@ -749,7 +992,7 @@ import {
View,
} from 'react-native';
-const { UIManager } = NativeModules;
+const {UIManager} = NativeModules;
UIManager.setLayoutAnimationEnabledExperimental &&
UIManager.setLayoutAnimationEnabledExperimental(true);
@@ -763,13 +1006,15 @@ export default class App extends React.Component {
_onPress = () => {
// Animate the update
LayoutAnimation.spring();
- this.setState({w: this.state.w + 15, h: this.state.h + 15})
- }
+ this.setState({w: this.state.w + 15, h: this.state.h + 15});
+ };
render() {
return (
-
+ Press me!
diff --git a/docs/appearance.md b/docs/appearance.md
index 8e742ba0821..0bc4ec8c7e3 100644
--- a/docs/appearance.md
+++ b/docs/appearance.md
@@ -5,8 +5,8 @@ title: Appearance
import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
-```jsx
-import { Appearance } from 'react-native';
+```tsx
+import {Appearance} from 'react-native';
```
The `Appearance` module exposes information about the user's appearance preferences, such as their preferred color scheme (light or dark).
@@ -36,7 +36,7 @@ The `Appearance` module exposes information about the user's appearance preferen
You can use the `Appearance` module to determine if the user prefers a dark color scheme:
-```jsx
+```tsx
const colorScheme = Appearance.getColorScheme();
if (colorScheme === 'dark') {
// Use dark color scheme
@@ -53,8 +53,8 @@ Although the color scheme is available immediately, this may change (e.g. schedu
### `getColorScheme()`
-```jsx
-static getColorScheme()
+```tsx
+static getColorScheme(): 'light' | 'dark' | null;
```
Indicates the current user preferred color scheme. The value may be updated later, either through direct user action (e.g. theme selection in device settings) or on a schedule (e.g. light and dark themes that follow the day/night cycle).
@@ -73,18 +73,10 @@ See also: `useColorScheme` hook.
### `addChangeListener()`
-```jsx
-static addChangeListener(listener)
+```tsx
+static addChangeListener(
+ listener: (preferences: {colorScheme: 'light' | 'dark' | null}) => void,
+): NativeEventSubscription;
```
Add an event handler that is fired when appearance preferences change.
-
----
-
-### `removeChangeListener()`
-
-```jsx
-static removeChangeListener(listener)
-```
-
-> **Deprecated.** Use the `remove()` method on the event subscription returned by [`addChangeListener()`](#addchangelistener).
diff --git a/docs/appregistry.md b/docs/appregistry.md
index 0adf5b64772..4db609c8fbd 100644
--- a/docs/appregistry.md
+++ b/docs/appregistry.md
@@ -12,10 +12,10 @@ title: AppRegistry
`AppRegistry` is the JS entry point to running all React Native apps. App root components should register themselves with `AppRegistry.registerComponent`, then the native system can load the bundle for the app and then actually run the app when it's ready by invoking `AppRegistry.runApplication`.
-```jsx
-import { Text, AppRegistry } from 'react-native';
+```tsx
+import {Text, AppRegistry} from 'react-native';
-const App = (props) => (
+const App = () => (
App1
@@ -34,41 +34,10 @@ To "stop" an application when a view should be destroyed, call `AppRegistry.unmo
## Methods
-### `cancelHeadlessTask()`
-
-```jsx
-static cancelHeadlessTask(taskId, taskKey)
-```
-
-Only called from native code. Cancels a headless task.
-
-**Parameters:**
-
-| Name | Type | Description |
-| ------------------------------------------------------------ | ------ | --------------------------------------------------------------------------------------- |
-| taskId
Required
| number | The native id for this task instance that was used when `startHeadlessTask` was called. |
-| taskKey
Required
| string | The key for the task that was used when `startHeadlessTask` was called. |
-
----
-
-### `enableArchitectureIndicator()`
-
-```jsx
-static enableArchitectureIndicator(enabled)
-```
-
-**Parameters:**
-
-| Name | Type |
-| ------------------------------------------------------------ | ------- |
-| enabled
Required
| boolean |
-
----
-
### `getAppKeys()`
-```jsx
-static getAppKeys()
+```tsx
+static getAppKeys(): string[];
```
Returns an array of strings.
@@ -77,8 +46,8 @@ Returns an array of strings.
### `getRegistry()`
-```jsx
-static getRegistry()
+```tsx
+static getRegistry(): {sections: string[]; runnables: Runnable[]};
```
Returns a [Registry](appregistry#registry) object.
@@ -87,8 +56,8 @@ Returns a [Registry](appregistry#registry) object.
### `getRunnable()`
-```jsx
-static getRunnable(appKey)
+```tsx
+static getRunnable(appKey: string): : Runnable | undefined;
```
Returns a [Runnable](appregistry#runnable) object.
@@ -103,8 +72,8 @@ Returns a [Runnable](appregistry#runnable) object.
### `getSectionKeys()`
-```jsx
-static getSectionKeys()
+```tsx
+static getSectionKeys(): string[];
```
Returns an array of strings.
@@ -113,8 +82,8 @@ Returns an array of strings.
### `getSections()`
-```jsx
-static getSections()
+```tsx
+static getSections(): Record;
```
Returns a [Runnables](appregistry#runnables) object.
@@ -123,8 +92,12 @@ Returns a [Runnables](appregistry#runnables) object.
### `registerCancellableHeadlessTask()`
-```jsx
-static registerCancellableHeadlessTask(taskKey, taskProvider, taskCancelProvider)
+```tsx
+static registerCancellableHeadlessTask(
+ taskKey: string,
+ taskProvider: TaskProvider,
+ taskCancelProvider: TaskCancelProvider,
+);
```
Register a headless task which can be cancelled. A headless task is a bit of code that runs without a UI.
@@ -141,8 +114,12 @@ Register a headless task which can be cancelled. A headless task is a bit of cod
### `registerComponent()`
-```jsx
-static registerComponent(appKey, componentProvider, section?)
+```tsx
+static registerComponent(
+ appKey: string,
+ getComponentFunc: ComponentProvider,
+ section?: boolean,
+): string;
```
**Parameters:**
@@ -157,22 +134,25 @@ static registerComponent(appKey, componentProvider, section?)
### `registerConfig()`
-```jsx
-static registerConfig(config)
+```tsx
+static registerConfig(config: AppConfig[]);
```
**Parameters:**
-| Name | Type |
-| ----------------------------------------------------------- | ---------------------------------- |
-| config
Required
| [AppConfig](appregistry#appconfig) |
+| Name | Type |
+| ----------------------------------------------------------- | ------------------------------------ |
+| config
Required
| [AppConfig](appregistry#appconfig)[] |
---
### `registerHeadlessTask()`
-```jsx
-static registerHeadlessTask(taskKey, taskProvider)
+```tsx
+static registerHeadlessTask(
+ taskKey: string,
+ taskProvider: TaskProvider,
+);
```
Register a headless task. A headless task is a bit of code that runs without a UI.
@@ -190,8 +170,8 @@ This is a way to run tasks in JavaScript while your app is in the background. It
### `registerRunnable()`
-```jsx
-static registerRunnable(appKey, run)
+```tsx
+static registerRunnable(appKey: string, func: Runnable): string;
```
**Parameters:**
@@ -205,8 +185,11 @@ static registerRunnable(appKey, run)
### `registerSection()`
-```jsx
-static registerSection(appKey, component)
+```tsx
+static registerSection(
+ appKey: string,
+ component: ComponentProvider,
+);
```
**Parameters:**
@@ -220,8 +203,8 @@ static registerSection(appKey, component)
### `runApplication()`
-```jsx
-static runApplication(appKey, appParameters)
+```tsx
+static runApplication(appKey: string, appParameters: any): void;
```
Loads the JavaScript bundle and runs the app.
@@ -237,8 +220,10 @@ Loads the JavaScript bundle and runs the app.
### `setComponentProviderInstrumentationHook()`
-```jsx
-static setComponentProviderInstrumentationHook(hook)
+```tsx
+static setComponentProviderInstrumentationHook(
+ hook: ComponentProviderInstrumentationHook,
+);
```
**Parameters:**
@@ -260,8 +245,10 @@ The function must also return a React Component.
### `setWrapperComponentProvider()`
-```jsx
-static setWrapperComponentProvider(provider)
+```tsx
+static setWrapperComponentProvider(
+ provider: WrapperComponentProvider,
+);
```
**Parameters:**
@@ -274,8 +261,12 @@ static setWrapperComponentProvider(provider)
### `startHeadlessTask()`
-```jsx
-static startHeadlessTask(taskId, taskKey, data)
+```tsx
+static startHeadlessTask(
+ taskId: number,
+ taskKey: string,
+ data: any,
+);
```
Only called from native code. Starts a headless task.
@@ -292,8 +283,8 @@ Only called from native code. Starts a headless task.
### `unmountApplicationComponentAtRootTag()`
-```jsx
-static unmountApplicationComponentAtRootTag(rootTag)
+```tsx
+static unmountApplicationComponentAtRootTag(rootTag: number);
```
Stops an application when a view should be destroyed.
diff --git a/docs/appstate.md b/docs/appstate.md
index 9ba3b7d3533..8a65cf9e9cf 100644
--- a/docs/appstate.md
+++ b/docs/appstate.md
@@ -28,25 +28,25 @@ To see the current state, you can check `AppState.currentState`, which will be k
```SnackPlayer name=AppState%20Function%20Component%20Example
-import React, { useRef, useState, useEffect } from "react";
-import { AppState, StyleSheet, Text, View } from "react-native";
+import React, {useRef, useState, useEffect} from 'react';
+import {AppState, StyleSheet, Text, View} from 'react-native';
const AppStateExample = () => {
const appState = useRef(AppState.currentState);
const [appStateVisible, setAppStateVisible] = useState(appState.current);
useEffect(() => {
- const subscription = AppState.addEventListener("change", nextAppState => {
+ const subscription = AppState.addEventListener('change', nextAppState => {
if (
appState.current.match(/inactive|background/) &&
- nextAppState === "active"
+ nextAppState === 'active'
) {
- console.log("App has come to the foreground!");
+ console.log('App has come to the foreground!');
}
appState.current = nextAppState;
setAppStateVisible(appState.current);
- console.log("AppState", appState.current);
+ console.log('AppState', appState.current);
});
return () => {
@@ -64,8 +64,8 @@ const AppStateExample = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center",
- alignItems: "center",
+ justifyContent: 'center',
+ alignItems: 'center',
},
});
@@ -77,27 +77,30 @@ If you don't want to see the AppState update from `active` to `inactive` on iOS
-```SnackPlayer name=AppState%20Class%20Component%20Example
-import React, { Component } from "react";
-import { AppState, StyleSheet, Text, View } from "react-native";
+
+
+
+```SnackPlayer name=AppState%20Class%20Component%20Example&ext=js
+import React, {Component} from 'react';
+import {AppState, StyleSheet, Text, View} from 'react-native';
class AppStateExample extends Component {
state = {
- appState: AppState.currentState
+ appState: AppState.currentState,
};
componentDidMount() {
this.appStateSubscription = AppState.addEventListener(
- "change",
+ 'change',
nextAppState => {
if (
this.state.appState.match(/inactive|background/) &&
- nextAppState === "active"
+ nextAppState === 'active'
) {
- console.log("App has come to the foreground!");
+ console.log('App has come to the foreground!');
}
- this.setState({ appState: nextAppState });
- }
+ this.setState({appState: nextAppState});
+ },
);
}
@@ -117,9 +120,62 @@ class AppStateExample extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center",
- alignItems: "center"
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+export default AppStateExample;
+```
+
+
+
+
+```SnackPlayer name=AppState%20Class%20Component%20Example&ext=tsx
+import React, {Component} from 'react';
+import {AppState, StyleSheet, Text, View} from 'react-native';
+import type {NativeEventSubscription} from 'react-native';
+
+class AppStateExample extends Component {
+ appStateSubscription?: NativeEventSubscription;
+ state = {
+ appState: AppState.currentState,
+ };
+
+ componentDidMount() {
+ this.appStateSubscription = AppState.addEventListener(
+ 'change',
+ nextAppState => {
+ if (
+ this.state.appState.match(/inactive|background/) &&
+ nextAppState === 'active'
+ ) {
+ console.log('App has come to the foreground!');
+ }
+ this.setState({appState: nextAppState});
+ },
+ );
}
+
+ componentWillUnmount() {
+ this.appStateSubscription?.remove();
+ }
+
+ render() {
+ return (
+
+ Current state is: {this.state.appState}
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
});
export default AppStateExample;
@@ -128,6 +184,9 @@ export default AppStateExample;
+
+
+
This example will only ever appear to say "Current state is: active" because the app is only visible to the user when in the `active` state, and the null state will happen only momentarily. If you want to experiment with the code we recommend to use your own device instead of embedded preview.
---
@@ -156,27 +215,20 @@ Received when the user is not actively interacting with the app. Useful in situa
### `addEventListener()`
-```jsx
-addEventListener(eventType, listener);
+```tsx
+static addEventListener(
+ type: AppStateEvent,
+ listener: (state: AppStateStatus) => void,
+): NativeEventSubscription;
```
Sets up a function that will be called whenever the specified event type on AppState occurs. Valid values for `eventType` are
[listed above](#events). Returns the `EventSubscription`.
----
-
-### `removeEventListener()`
-
-```jsx
-removeEventListener(eventType, listener);
-```
-
-> **Deprecated.** Use the `remove()` method on the `EventSubscription` returned by [`addEventListener()`](#addeventlistener).
-
## Properties
### `currentState`
-```jsx
-AppState.currentState;
+```tsx
+static currentState: AppStateStatus;
```
diff --git a/docs/asyncstorage.md b/docs/asyncstorage.md
index 04e507f8b57..2b5fc0cfe04 100644
--- a/docs/asyncstorage.md
+++ b/docs/asyncstorage.md
@@ -3,7 +3,7 @@ id: asyncstorage
title: 'đ§ AsyncStorage'
---
-> **Deprecated.** Use one of the [community packages](https://reactnative.directory/?search=storage) instead.
+> **Removed.** Use one of the [community packages](https://reactnative.directory/?search=storage) instead.
`AsyncStorage` is an unencrypted, asynchronous, persistent, key-value storage system that is global to the app. It should be used instead of LocalStorage.
@@ -16,7 +16,7 @@ The `AsyncStorage` JavaScript code is a facade that provides a clear JavaScript
Importing the `AsyncStorage` library:
```jsx
-import { AsyncStorage } from 'react-native';
+import {AsyncStorage} from 'react-native';
```
Persisting data:
@@ -26,7 +26,7 @@ _storeData = async () => {
try {
await AsyncStorage.setItem(
'@MySuperStore:key',
- 'I like to save it.'
+ 'I like to save it.',
);
} catch (error) {
// Error saving data
@@ -132,12 +132,12 @@ Example:
let UID123_object = {
name: 'Chris',
age: 30,
- traits: { hair: 'brown', eyes: 'brown' }
+ traits: {hair: 'brown', eyes: 'brown'},
};
// You only need to define what will be added or updated
let UID123_delta = {
age: 31,
- traits: { eyes: 'blue', shoe_size: 10 }
+ traits: {eyes: 'blue', shoe_size: 10},
};
AsyncStorage.setItem(
@@ -151,9 +151,9 @@ AsyncStorage.setItem(
AsyncStorage.getItem('UID123', (err, result) => {
console.log(result);
});
- }
+ },
);
- }
+ },
);
// Console log result:
@@ -284,7 +284,7 @@ Example:
```jsx
let keys = ['k1', 'k2'];
-AsyncStorage.multiRemove(keys, (err) => {
+AsyncStorage.multiRemove(keys, err => {
// keys k1 & k2 removed, if they existed
// do most stuff after removal (if you want)
});
@@ -316,39 +316,39 @@ Example:
let UID234_object = {
name: 'Chris',
age: 30,
- traits: { hair: 'brown', eyes: 'brown' }
+ traits: {hair: 'brown', eyes: 'brown'},
};
// first user, delta values
let UID234_delta = {
age: 31,
- traits: { eyes: 'blue', shoe_size: 10 }
+ traits: {eyes: 'blue', shoe_size: 10},
};
// second user, initial values
let UID345_object = {
name: 'Marge',
age: 25,
- traits: { hair: 'blonde', eyes: 'blue' }
+ traits: {hair: 'blonde', eyes: 'blue'},
};
// second user, delta values
let UID345_delta = {
age: 26,
- traits: { eyes: 'green', shoe_size: 6 }
+ traits: {eyes: 'green', shoe_size: 6},
};
let multi_set_pairs = [
['UID234', JSON.stringify(UID234_object)],
- ['UID345', JSON.stringify(UID345_object)]
+ ['UID345', JSON.stringify(UID345_object)],
];
let multi_merge_pairs = [
['UID234', JSON.stringify(UID234_delta)],
- ['UID345', JSON.stringify(UID345_delta)]
+ ['UID345', JSON.stringify(UID345_delta)],
];
-AsyncStorage.multiSet(multi_set_pairs, (err) => {
- AsyncStorage.multiMerge(multi_merge_pairs, (err) => {
+AsyncStorage.multiSet(multi_set_pairs, err => {
+ AsyncStorage.multiMerge(multi_merge_pairs, err => {
AsyncStorage.multiGet(['UID234', 'UID345'], (err, stores) => {
stores.map((result, i, store) => {
let key = store[i][0];
diff --git a/docs/backhandler.md b/docs/backhandler.md
index f86a5730492..43ed22af140 100644
--- a/docs/backhandler.md
+++ b/docs/backhandler.md
@@ -16,7 +16,7 @@ The event subscriptions are called in reverse order (i.e. the last registered su
## Pattern
-```jsx
+```tsx
BackHandler.addEventListener('hardwareBackPress', function () {
/**
* this.onMainScreen and this.goBack are just examples,
@@ -49,26 +49,26 @@ The following example implements a scenario where you confirm if the user wants
```SnackPlayer name=BackHandler&supportedPlatforms=android
-import React, { useEffect } from "react";
-import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
+import React, {useEffect} from 'react';
+import {Text, View, StyleSheet, BackHandler, Alert} from 'react-native';
const App = () => {
useEffect(() => {
const backAction = () => {
- Alert.alert("Hold on!", "Are you sure you want to go back?", [
+ Alert.alert('Hold on!', 'Are you sure you want to go back?', [
{
- text: "Cancel",
+ text: 'Cancel',
onPress: () => null,
- style: "cancel"
+ style: 'cancel',
},
- { text: "YES", onPress: () => BackHandler.exitApp() }
+ {text: 'YES', onPress: () => BackHandler.exitApp()},
]);
return true;
};
const backHandler = BackHandler.addEventListener(
- "hardwareBackPress",
- backAction
+ 'hardwareBackPress',
+ backAction,
);
return () => backHandler.remove();
@@ -84,13 +84,13 @@ const App = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
text: {
fontSize: 18,
- fontWeight: "bold"
- }
+ fontWeight: 'bold',
+ },
});
export default App;
@@ -99,27 +99,30 @@ export default App;
-```SnackPlayer name=BackHandler&supportedPlatforms=android
-import React, { Component } from "react";
-import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
+
+
+
+```SnackPlayer name=BackHandler&supportedPlatforms=android&ext=js
+import React, {Component} from 'react';
+import {Text, View, StyleSheet, BackHandler, Alert} from 'react-native';
class App extends Component {
backAction = () => {
- Alert.alert("Hold on!", "Are you sure you want to go back?", [
+ Alert.alert('Hold on!', 'Are you sure you want to go back?', [
{
- text: "Cancel",
+ text: 'Cancel',
onPress: () => null,
- style: "cancel"
+ style: 'cancel',
},
- { text: "YES", onPress: () => BackHandler.exitApp() }
+ {text: 'YES', onPress: () => BackHandler.exitApp()},
]);
return true;
};
componentDidMount() {
this.backHandler = BackHandler.addEventListener(
- "hardwareBackPress",
- this.backAction
+ 'hardwareBackPress',
+ this.backAction,
);
}
@@ -134,105 +137,55 @@ class App extends Component {
);
}
-};
+}
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
text: {
fontSize: 18,
- fontWeight: "bold"
- }
-});
-
-export default App;
-```
-
-
-
-
-`BackHandler.addEventListener` creates an event listener & returns a `NativeEventSubscription` object which should be cleared using `NativeEventSubscription.remove` method.
-
-Additionally `BackHandler.removeEventListener` can also be used to clear the event listener. Ensure the callback has the reference to the same function used in the `addEventListener` call as shown the following example 
-
-
-
-
-```SnackPlayer name=BackHandler&supportedPlatforms=android
-import React, { useEffect } from "react";
-import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
-
-const App = () => {
- const backAction = () => {
- Alert.alert("Hold on!", "Are you sure you want to go back?", [
- {
- text: "Cancel",
- onPress: () => null,
- style: "cancel"
- },
- { text: "YES", onPress: () => BackHandler.exitApp() }
- ]);
- return true;
- };
-
- useEffect(() => {
- BackHandler.addEventListener("hardwareBackPress", backAction);
-
- return () =>
- BackHandler.removeEventListener("hardwareBackPress", backAction);
- }, []);
-
- return (
-
- Click Back button!
-
- );
-};
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ fontWeight: 'bold',
},
- text: {
- fontSize: 18,
- fontWeight: "bold"
- }
});
export default App;
```
-
+
-```SnackPlayer name=BackHandler&supportedPlatforms=android
-import React, { Component } from "react";
-import { Text, View, StyleSheet, BackHandler, Alert } from "react-native";
+```SnackPlayer name=BackHandler&supportedPlatforms=android&ext=tsx
+import React, {Component} from 'react';
+import {Text, View, StyleSheet, BackHandler, Alert} from 'react-native';
+import type {NativeEventSubscription} from 'react-native';
class App extends Component {
+ backHandler?: NativeEventSubscription;
+
backAction = () => {
- Alert.alert("Hold on!", "Are you sure you want to go back?", [
+ Alert.alert('Hold on!', 'Are you sure you want to go back?', [
{
- text: "Cancel",
+ text: 'Cancel',
onPress: () => null,
- style: "cancel"
+ style: 'cancel',
},
- { text: "YES", onPress: () => BackHandler.exitApp() }
+ {text: 'YES', onPress: () => BackHandler.exitApp()},
]);
return true;
};
componentDidMount() {
- BackHandler.addEventListener("hardwareBackPress", this.backAction);
+ this.backHandler = BackHandler.addEventListener(
+ 'hardwareBackPress',
+ this.backAction,
+ );
}
componentWillUnmount() {
- BackHandler.removeEventListener("hardwareBackPress", this.backAction);
+ this.backHandler?.remove();
}
render() {
@@ -242,18 +195,18 @@ class App extends Component {
);
}
-};
+}
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
text: {
fontSize: 18,
- fontWeight: "bold"
- }
+ fontWeight: 'bold',
+ },
});
export default App;
@@ -261,6 +214,10 @@ export default App;
+
+
+
+`BackHandler.addEventListener` creates an event listener & returns a `NativeEventSubscription` object which should be cleared using `NativeEventSubscription.remove` method.
## Usage with React Navigation
@@ -278,22 +235,28 @@ If you are using React Navigation to navigate across different screens, you can
### `addEventListener()`
-```jsx
-static addEventListener(eventName, handler)
+```tsx
+static addEventListener(
+ eventName: BackPressEventName,
+ handler: () => boolean | null | undefined,
+): NativeEventSubscription;
```
---
### `exitApp()`
-```jsx
-static exitApp()
+```tsx
+static exitApp();
```
---
### `removeEventListener()`
-```jsx
-static removeEventListener(eventName, handler)
+```tsx
+static removeEventListener(
+ eventName: BackPressEventName,
+ handler: () => boolean | null | undefined,
+);
```
diff --git a/docs/build-speed.md b/docs/build-speed.md
index e1ed3ec0031..2fa1f1b763f 100644
--- a/docs/build-speed.md
+++ b/docs/build-speed.md
@@ -6,22 +6,21 @@ title: Speeding up your Build phase
Building your React Native app could be **expensive** and take several minutes of developers time.
This can be problematic as your project grows and generally in bigger organizations with multiple React Native developers.
-With [the New React Native Architecture](new-architecture-app-intro), this problem is becoming more critical
-as you might have to compile some native C++ code in your project with the Android NDK in addition to the native code already necessary for the iOS and Android platforms.
-
To mitigate this performance hit, this page shares some suggestions on how to **improve your build time**.
+:::info
+If you're noticing slower build time with the **New Architecture on Android**, we recommend to upgrade to React Native 0.71
+:::
+
## Build only one ABI during development (Android-only)
When building your android app locally, by default you build all the 4 [Application Binary Interfaces (ABIs)](https://developer.android.com/ndk/guides/abis) : `armeabi-v7a`, `arm64-v8a`, `x86` & `x86_64`.
However, you probably don't need to build all of them if you're building locally and testing your emulator or on a physical device.
-This should reduce your build time by a **~75% factor**.
+This should reduce your **native build time** by a ~75% factor.
-If you're using the React Native CLI, you can use the `--active-arch-only` flag together with the `run-android` command.
-This flag will make sure the correct ABI is picked up from either the running emulator or the plugged in phone.
-To confirm that this approach is working fine, you'll see a message like `info Detected architectures arm64-v8a` on console.
+If you're using the React Native CLI, you can add the `--active-arch-only` flag to the `run-android` command. This flag will make sure the correct ABI is picked up from either the running emulator or the plugged in phone. To confirm that this approach is working fine, you'll see a message like `info Detected architectures arm64-v8a` on console.
```
$ yarn react-native run-android --active-arch-only
@@ -75,7 +74,7 @@ if an intermediate compilation result was originally stored.
To install it, you can follow the [official installation instructions](https://github.com/ccache/ccache/blob/master/doc/INSTALL.md).
-On Mac OS, we can install ccache with `brew install ccache`.
+On macOS, we can install ccache with `brew install ccache`.
Once installed you can configure it as follows to cache NDK compile results:
```
diff --git a/docs/building-for-tv.md b/docs/building-for-tv.md
index f5e52bf1400..3b18715bc0d 100644
--- a/docs/building-for-tv.md
+++ b/docs/building-for-tv.md
@@ -49,7 +49,7 @@ var running_on_android_tv = Platform.isTV;
- _TV remote/keyboard input_: A new native class, `ReactAndroidTVRootViewHelper`, sets up key events handlers for TV remote events. When TV remote events occur, this class fires a JS event. This event will be picked up by instances of the `TVEventHandler` JavaScript object. Application code that needs to implement custom handling of TV remote events can create an instance of `TVEventHandler` and listen for these events, as in the following code:
-```jsx
+```tsx
var TVEventHandler = require('TVEventHandler');
class Game2048 extends React.Component {
@@ -59,13 +59,13 @@ class Game2048 extends React.Component {
this._tvEventHandler = new TVEventHandler();
this._tvEventHandler.enable(this, function (cmp, evt) {
if (evt && evt.eventType === 'right') {
- cmp.setState({ board: cmp.state.board.move(2) });
+ cmp.setState({board: cmp.state.board.move(2)});
} else if (evt && evt.eventType === 'up') {
- cmp.setState({ board: cmp.state.board.move(1) });
+ cmp.setState({board: cmp.state.board.move(1)});
} else if (evt && evt.eventType === 'left') {
- cmp.setState({ board: cmp.state.board.move(0) });
+ cmp.setState({board: cmp.state.board.move(0)});
} else if (evt && evt.eventType === 'down') {
- cmp.setState({ board: cmp.state.board.move(3) });
+ cmp.setState({board: cmp.state.board.move(3)});
} else if (evt && evt.eventType === 'playPause') {
cmp.restartGame();
}
@@ -112,7 +112,7 @@ class Game2048 extends React.Component {
- _JavaScript layer_: Support for Apple TV has been added to `Platform.ios.js`. You can check whether code is running on AppleTV by doing
-```jsx
+```tsx
var Platform = require('Platform');
var running_on_tv = Platform.isTV;
@@ -135,7 +135,7 @@ var running_on_apple_tv = Platform.isTVOS;
- _TV remote/keyboard input_: A new native class, `RCTTVRemoteHandler`, sets up gesture recognizers for TV remote events. When TV remote events occur, this class fires notifications that are picked up by `RCTTVNavigationEventEmitter` (a subclass of `RCTEventEmitter`), that fires a JS event. This event will be picked up by instances of the `TVEventHandler` JavaScript object. Application code that needs to implement custom handling of TV remote events can create an instance of `TVEventHandler` and listen for these events, as in the following code:
-```jsx
+```tsx
var TVEventHandler = require('TVEventHandler');
class Game2048 extends React.Component {
@@ -145,13 +145,13 @@ class Game2048 extends React.Component {
this._tvEventHandler = new TVEventHandler();
this._tvEventHandler.enable(this, function (cmp, evt) {
if (evt && evt.eventType === 'right') {
- cmp.setState({ board: cmp.state.board.move(2) });
+ cmp.setState({board: cmp.state.board.move(2)});
} else if (evt && evt.eventType === 'up') {
- cmp.setState({ board: cmp.state.board.move(1) });
+ cmp.setState({board: cmp.state.board.move(1)});
} else if (evt && evt.eventType === 'left') {
- cmp.setState({ board: cmp.state.board.move(0) });
+ cmp.setState({board: cmp.state.board.move(0)});
} else if (evt && evt.eventType === 'down') {
- cmp.setState({ board: cmp.state.board.move(3) });
+ cmp.setState({board: cmp.state.board.move(3)});
} else if (evt && evt.eventType === 'playPause') {
cmp.restartGame();
}
diff --git a/docs/button.md b/docs/button.md
index 78f7fcaa637..e3167c4bbff 100644
--- a/docs/button.md
+++ b/docs/button.md
@@ -5,9 +5,9 @@ title: Button
A basic button component that should render nicely on any platform. Supports a minimal level of customization.
-If this button doesn't look right for your app, you can build your own button using [TouchableOpacity](touchableopacity) or [TouchableWithoutFeedback](touchablewithoutfeedback). For inspiration, look at the [source code for this button component](https://github.com/facebook/react-native/blob/master/Libraries/Components/Button.js). Or, take a look at the [wide variety of button components built by the community](https://js.coach/?menu%5Bcollections%5D=React%20Native&page=1&query=button).
+If this button doesn't look right for your app, you can build your own button using [Pressable](pressable). For inspiration, look at the [source code for the Button component](https://github.com/facebook/react-native/blob/main/Libraries/Components/Button.js).
-```jsx
+```tsx
drawer.current.openDrawer()}
+ onPress={() => drawer.current?.openDrawer()}
/>
@@ -62,23 +150,26 @@ const App = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center",
- padding: 16
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 16,
},
navigationContainer: {
- backgroundColor: "#ecf0f1"
+ backgroundColor: '#ecf0f1',
},
paragraph: {
padding: 16,
fontSize: 15,
- textAlign: "center"
- }
+ textAlign: 'center',
+ },
});
export default App;
```
+
+
+
---
# Reference
@@ -95,7 +186,7 @@ Inherits [View Props](view.md#props).
Specifies the background color of the drawer. The default value is `white`. If you want to set the opacity of the drawer, use rgba. Example:
-```jsx
+```tsx
return (
);
@@ -220,7 +311,7 @@ Make the drawer take the entire screen and draw the background of the status bar
### `closeDrawer()`
-```jsx
+```tsx
closeDrawer();
```
@@ -230,7 +321,7 @@ Closes the drawer.
### `openDrawer()`
-```jsx
+```tsx
openDrawer();
```
diff --git a/docs/dynamiccolorios.md b/docs/dynamiccolorios.md
index 946cb865359..b7af9f44320 100644
--- a/docs/dynamiccolorios.md
+++ b/docs/dynamiccolorios.md
@@ -7,12 +7,12 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import con
The `DynamicColorIOS` function is a platform color type specific to iOS.
-```jsx
+```tsx
DynamicColorIOS({
light: color,
dark: color,
highContrastLight: color, // (optional) will fallback to "light" if not provided
- highContrastDark: color // (optional) will fallback to "dark" if not provided
+ highContrastDark: color, // (optional) will fallback to "dark" if not provided
});
```
@@ -38,18 +38,18 @@ At runtime, the system will choose which of the colors to display depending on t
## Example
-```jsx
-import { DynamicColorIOS } from 'react-native';
+```tsx
+import {DynamicColorIOS} from 'react-native';
const customDynamicTextColor = DynamicColorIOS({
dark: 'lightskyblue',
- light: 'midnightblue'
+ light: 'midnightblue',
});
const customContrastDynamicTextColor = DynamicColorIOS({
dark: 'darkgray',
light: 'lightgray',
highContrastDark: 'black',
- highContrastLight: 'white'
+ highContrastLight: 'white',
});
```
diff --git a/docs/easing.md b/docs/easing.md
index 1615607e4b6..e0f30cfa6a0 100644
--- a/docs/easing.md
+++ b/docs/easing.md
@@ -3,6 +3,8 @@ id: easing
title: Easing
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
The `Easing` module implements common easing functions. This module is used by [`Animated.timing()`](animated.md#timing) to convey physically believable motion in animations.
You can find a visualization of some common easing functions at http://easings.net/
@@ -43,9 +45,21 @@ The following helpers are used to modify other easing functions.
## Example
-```SnackPlayer name=Easing%20Demo
-import React from "react";
-import { Animated, Easing, SectionList, StatusBar, StyleSheet, Text, TouchableOpacity, View } from "react-native";
+
+
+
+```SnackPlayer name=Easing%20Demo&ext=js
+import React from 'react';
+import {
+ Animated,
+ Easing,
+ SectionList,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
const App = () => {
let opacity = new Animated.Value(0);
@@ -55,13 +69,14 @@ const App = () => {
Animated.timing(opacity, {
toValue: 1,
duration: 1200,
- easing
+ easing,
+ useNativeDriver: true,
}).start();
};
const size = opacity.interpolate({
inputRange: [0, 1],
- outputRange: [0, 80]
+ outputRange: [0, 80],
});
const animatedStyles = [
@@ -69,32 +84,29 @@ const App = () => {
{
opacity,
width: size,
- height: size
- }
+ height: size,
+ },
];
return (
-
- Press rows below to preview the Easing!
-
+ Press rows below to preview the Easing! item.title}
- renderItem={({ item }) => (
+ keyExtractor={item => item.title}
+ renderItem={({item}) => (
animate(item.easing)}
- style={styles.listRow}
- >
+ style={styles.listRow}>
{item.title}
)}
- renderSectionHeader={({ section: { title } }) => (
+ renderSectionHeader={({section: {title}}) => (
{title}
)}
/>
@@ -104,90 +116,249 @@ const App = () => {
const SECTIONS = [
{
- title: "Predefined animations",
+ title: 'Predefined animations',
data: [
- { title: "Bounce", easing: Easing.bounce },
- { title: "Ease", easing: Easing.ease },
- { title: "Elastic", easing: Easing.elastic(4) }
- ]
+ {title: 'Bounce', easing: Easing.bounce},
+ {title: 'Ease', easing: Easing.ease},
+ {title: 'Elastic', easing: Easing.elastic(4)},
+ ],
},
{
- title: "Standard functions",
+ title: 'Standard functions',
data: [
- { title: "Linear", easing: Easing.linear },
- { title: "Quad", easing: Easing.quad },
- { title: "Cubic", easing: Easing.cubic }
- ]
+ {title: 'Linear', easing: Easing.linear},
+ {title: 'Quad', easing: Easing.quad},
+ {title: 'Cubic', easing: Easing.cubic},
+ ],
},
{
- title: "Additional functions",
+ title: 'Additional functions',
data: [
{
- title: "Bezier",
- easing: Easing.bezier(0, 2, 1, -1)
+ title: 'Bezier',
+ easing: Easing.bezier(0, 2, 1, -1),
},
- { title: "Circle", easing: Easing.circle },
- { title: "Sin", easing: Easing.sin },
- { title: "Exp", easing: Easing.exp }
- ]
+ {title: 'Circle', easing: Easing.circle},
+ {title: 'Sin', easing: Easing.sin},
+ {title: 'Exp', easing: Easing.exp},
+ ],
},
{
- title: "Combinations",
+ title: 'Combinations',
data: [
{
- title: "In + Bounce",
- easing: Easing.in(Easing.bounce)
+ title: 'In + Bounce',
+ easing: Easing.in(Easing.bounce),
},
{
- title: "Out + Exp",
- easing: Easing.out(Easing.exp)
+ title: 'Out + Exp',
+ easing: Easing.out(Easing.exp),
},
{
- title: "InOut + Elastic",
- easing: Easing.inOut(Easing.elastic(1))
- }
- ]
- }
+ title: 'InOut + Elastic',
+ easing: Easing.inOut(Easing.elastic(1)),
+ },
+ ],
+ },
];
const styles = StyleSheet.create({
container: {
flex: 1,
- backgroundColor: "#20232a"
+ backgroundColor: '#20232a',
},
title: {
marginTop: 10,
- textAlign: "center",
- color: "#61dafb"
+ textAlign: 'center',
+ color: '#61dafb',
},
boxContainer: {
height: 160,
- alignItems: "center"
+ alignItems: 'center',
},
box: {
marginTop: 32,
borderRadius: 4,
- backgroundColor: "#61dafb"
+ backgroundColor: '#61dafb',
},
list: {
- backgroundColor: "#fff"
+ backgroundColor: '#fff',
},
listHeader: {
paddingHorizontal: 8,
paddingVertical: 4,
- backgroundColor: "#f4f4f4",
- color: "#999",
+ backgroundColor: '#f4f4f4',
+ color: '#999',
fontSize: 12,
- textTransform: "uppercase"
+ textTransform: 'uppercase',
},
listRow: {
- padding: 8
- }
+ padding: 8,
+ },
});
export default App;
```
+
+
+
+```SnackPlayer name=Easing%20Demo&ext=tsx
+import React from 'react';
+import {
+ Animated,
+ Easing,
+ SectionList,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+import type {EasingFunction} from 'react-native';
+
+const App = () => {
+ let opacity = new Animated.Value(0);
+
+ const animate = (easing: EasingFunction) => {
+ opacity.setValue(0);
+ Animated.timing(opacity, {
+ toValue: 1,
+ duration: 1200,
+ easing,
+ useNativeDriver: true,
+ }).start();
+ };
+
+ const size = opacity.interpolate({
+ inputRange: [0, 1],
+ outputRange: [0, 80],
+ });
+
+ const animatedStyles = [
+ styles.box,
+ {
+ opacity,
+ width: size,
+ height: size,
+ },
+ ];
+
+ return (
+
+
+ Press rows below to preview the Easing!
+
+
+
+ item.title}
+ renderItem={({item}) => (
+ animate(item.easing)}
+ style={styles.listRow}>
+ {item.title}
+
+ )}
+ renderSectionHeader={({section: {title}}) => (
+ {title}
+ )}
+ />
+
+ );
+};
+
+const SECTIONS = [
+ {
+ title: 'Predefined animations',
+ data: [
+ {title: 'Bounce', easing: Easing.bounce},
+ {title: 'Ease', easing: Easing.ease},
+ {title: 'Elastic', easing: Easing.elastic(4)},
+ ],
+ },
+ {
+ title: 'Standard functions',
+ data: [
+ {title: 'Linear', easing: Easing.linear},
+ {title: 'Quad', easing: Easing.quad},
+ {title: 'Cubic', easing: Easing.cubic},
+ ],
+ },
+ {
+ title: 'Additional functions',
+ data: [
+ {
+ title: 'Bezier',
+ easing: Easing.bezier(0, 2, 1, -1),
+ },
+ {title: 'Circle', easing: Easing.circle},
+ {title: 'Sin', easing: Easing.sin},
+ {title: 'Exp', easing: Easing.exp},
+ ],
+ },
+ {
+ title: 'Combinations',
+ data: [
+ {
+ title: 'In + Bounce',
+ easing: Easing.in(Easing.bounce),
+ },
+ {
+ title: 'Out + Exp',
+ easing: Easing.out(Easing.exp),
+ },
+ {
+ title: 'InOut + Elastic',
+ easing: Easing.inOut(Easing.elastic(1)),
+ },
+ ],
+ },
+];
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#20232a',
+ },
+ title: {
+ marginTop: 10,
+ textAlign: 'center',
+ color: '#61dafb',
+ },
+ boxContainer: {
+ height: 160,
+ alignItems: 'center',
+ },
+ box: {
+ marginTop: 32,
+ borderRadius: 4,
+ backgroundColor: '#61dafb',
+ },
+ list: {
+ backgroundColor: '#fff',
+ },
+ listHeader: {
+ paddingHorizontal: 8,
+ paddingVertical: 4,
+ backgroundColor: '#f4f4f4',
+ color: '#999',
+ fontSize: 12,
+ textTransform: 'uppercase',
+ },
+ listRow: {
+ padding: 8,
+ },
+});
+
+export default App;
+```
+
+
+
+
---
# Reference
@@ -196,8 +367,8 @@ export default App;
### `step0()`
-```jsx
-static step0(n)
+```tsx
+static step0(n: number);
```
A stepping function, returns 1 for any positive value of `n`.
@@ -206,8 +377,8 @@ A stepping function, returns 1 for any positive value of `n`.
### `step1()`
-```jsx
-static step1(n)
+```tsx
+static step1(n: number);
```
A stepping function, returns 1 if `n` is greater than or equal to 1.
@@ -216,8 +387,8 @@ A stepping function, returns 1 if `n` is greater than or equal to 1.
### `linear()`
-```jsx
-static linear(t)
+```tsx
+static linear(t: number);
```
A linear function, `f(t) = t`. Position correlates to elapsed time one to one.
@@ -228,8 +399,8 @@ http://cubic-bezier.com/#0,0,1,1
### `ease()`
-```jsx
-static ease(t)
+```tsx
+static ease(t: number);
```
A basic inertial interaction, similar to an object slowly accelerating to speed.
@@ -240,8 +411,8 @@ http://cubic-bezier.com/#.42,0,1,1
### `quad()`
-```jsx
-static quad(t)
+```tsx
+static quad(t: number);
```
A quadratic function, `f(t) = t * t`. Position equals the square of elapsed time.
@@ -252,8 +423,8 @@ http://easings.net/#easeInQuad
### `cubic()`
-```jsx
-static cubic(t)
+```tsx
+static cubic(t: number);
```
A cubic function, `f(t) = t * t * t`. Position equals the cube of elapsed time.
@@ -264,8 +435,8 @@ http://easings.net/#easeInCubic
### `poly()`
-```jsx
-static poly(n)
+```tsx
+static poly(n: number);
```
A power function. Position is equal to the Nth power of elapsed time.
@@ -276,8 +447,8 @@ n = 4: http://easings.net/#easeInQuart n = 5: http://easings.net/#easeInQuint
### `sin()`
-```jsx
-static sin(t)
+```tsx
+static sin(t: number);
```
A sinusoidal function.
@@ -288,8 +459,8 @@ http://easings.net/#easeInSine
### `circle()`
-```jsx
-static circle(t)
+```tsx
+static circle(t: number);
```
A circular function.
@@ -300,8 +471,8 @@ http://easings.net/#easeInCirc
### `exp()`
-```jsx
-static exp(t)
+```tsx
+static exp(t: number);
```
An exponential function.
@@ -312,8 +483,8 @@ http://easings.net/#easeInExpo
### `elastic()`
-```jsx
-static elastic(bounciness)
+```tsx
+static elastic(bounciness: number);
```
A basic elastic interaction, similar to a spring oscillating back and forth.
@@ -326,7 +497,7 @@ http://easings.net/#easeInElastic
### `back()`
-```jsx
+```tsx
static back(s)
```
@@ -336,8 +507,8 @@ Use with `Animated.parallel()` to create a basic effect where the object animate
### `bounce()`
-```jsx
-static bounce(t)
+```tsx
+static bounce(t: number);
```
Provides a basic bouncing effect.
@@ -348,8 +519,8 @@ http://easings.net/#easeInBounce
### `bezier()`
-```jsx
-static bezier(x1, y1, x2, y2)
+```tsx
+static bezier(x1: number, y1: number, x2: number, y2: number);
```
Provides a cubic bezier curve, equivalent to CSS Transitions' `transition-timing-function`.
@@ -360,11 +531,9 @@ A useful tool to visualize cubic bezier curves can be found at http://cubic-bezi
### `in()`
-
-```jsx
-static in(easing);
+```tsx
+static in(easing: number);
```
-
Runs an easing function forwards.
@@ -372,8 +541,8 @@ Runs an easing function forwards.
### `out()`
-```jsx
-static out(easing)
+```tsx
+static out(easing: number);
```
Runs an easing function backwards.
@@ -382,8 +551,8 @@ Runs an easing function backwards.
### `inOut()`
-```jsx
-static inOut(easing)
+```tsx
+static inOut(easing: number);
```
Makes any easing function symmetrical. The easing function will run forwards for half of the duration, then backwards for the rest of the duration.
diff --git a/docs/flatlist.md b/docs/flatlist.md
index 9314678a537..0b40f81e7e4 100644
--- a/docs/flatlist.md
+++ b/docs/flatlist.md
@@ -3,6 +3,8 @@ id: flatlist
title: FlatList
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
A performant interface for rendering basic, flat lists, supporting the most handy features:
- Fully cross-platform.
@@ -20,9 +22,19 @@ If you need section support, use [``](sectionlist.md).
## Example
-```SnackPlayer name=flatlist-simple
+
+
+
+```SnackPlayer name=flatlist-simple&ext=js
import React from 'react';
-import { SafeAreaView, View, FlatList, StyleSheet, Text, StatusBar } from 'react-native';
+import {
+ SafeAreaView,
+ View,
+ FlatList,
+ StyleSheet,
+ Text,
+ StatusBar,
+} from 'react-native';
const DATA = [
{
@@ -39,27 +51,91 @@ const DATA = [
},
];
-const Item = ({ title }) => (
+const Item = ({title}) => (
{title}
);
const App = () => {
- const renderItem = ({ item }) => (
-
+ return (
+
+ }
+ keyExtractor={item => item.id}
+ />
+
);
+};
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: StatusBar.currentHeight || 0,
+ },
+ item: {
+ backgroundColor: '#f9c2ff',
+ padding: 20,
+ marginVertical: 8,
+ marginHorizontal: 16,
+ },
+ title: {
+ fontSize: 32,
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=flatlist-simple&ext=tsx
+import React from 'react';
+import {
+ SafeAreaView,
+ View,
+ FlatList,
+ StyleSheet,
+ Text,
+ StatusBar,
+} from 'react-native';
+
+const DATA = [
+ {
+ id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
+ title: 'First Item',
+ },
+ {
+ id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
+ title: 'Second Item',
+ },
+ {
+ id: '58694a0f-3da1-471f-bd96-145571e29d72',
+ title: 'Third Item',
+ },
+];
+
+type ItemProps = {title: string};
+
+const Item = ({title}: ItemProps) => (
+
+ {title}
+
+);
+
+const App = () => {
return (
}
keyExtractor={item => item.id}
/>
);
-}
+};
const styles = StyleSheet.create({
container: {
@@ -80,6 +156,9 @@ const styles = StyleSheet.create({
export default App;
```
+
+
+
To render multiple columns, use the [`numColumns`](flatlist.md#numcolumns) prop. Using this approach instead of a `flexWrap` layout can prevent conflicts with the item height logic.
More complex, selectable example below.
@@ -87,44 +166,54 @@ More complex, selectable example below.
- By passing `extraData={selectedId}` to `FlatList` we make sure `FlatList` itself will re-render when the state changes. Without setting this prop, `FlatList` would not know it needs to re-render any items because it is a `PureComponent` and the prop comparison will not show any changes.
- `keyExtractor` tells the list to use the `id`s for the react keys instead of the default `key` property.
-```SnackPlayer name=flatlist-selectable
-import React, { useState } from "react";
-import { FlatList, SafeAreaView, StatusBar, StyleSheet, Text, TouchableOpacity } from "react-native";
+
+
+
+```SnackPlayer name=flatlist-selectable&ext=js
+import React, {useState} from 'react';
+import {
+ FlatList,
+ SafeAreaView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+} from 'react-native';
const DATA = [
{
- id: "bd7acbea-c1b1-46c2-aed5-3ad53abb28ba",
- title: "First Item",
+ id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
+ title: 'First Item',
},
{
- id: "3ac68afc-c605-48d3-a4f8-fbd91aa97f63",
- title: "Second Item",
+ id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
+ title: 'Second Item',
},
{
- id: "58694a0f-3da1-471f-bd96-145571e29d72",
- title: "Third Item",
+ id: '58694a0f-3da1-471f-bd96-145571e29d72',
+ title: 'Third Item',
},
];
-const Item = ({ item, onPress, backgroundColor, textColor }) => (
-
- {item.title}
+const Item = ({item, onPress, backgroundColor, textColor}) => (
+
+ {item.title}
);
const App = () => {
- const [selectedId, setSelectedId] = useState(null);
+ const [selectedId, setSelectedId] = useState();
- const renderItem = ({ item }) => {
- const backgroundColor = item.id === selectedId ? "#6e3b6e" : "#f9c2ff";
+ const renderItem = ({item}) => {
+ const backgroundColor = item.id === selectedId ? '#6e3b6e' : '#f9c2ff';
const color = item.id === selectedId ? 'white' : 'black';
return (
setSelectedId(item.id)}
- backgroundColor={{ backgroundColor }}
- textColor={{ color }}
+ backgroundColor={backgroundColor}
+ textColor={color}
/>
);
};
@@ -134,7 +223,7 @@ const App = () => {
item.id}
+ keyExtractor={item => item.id}
extraData={selectedId}
/>
@@ -159,6 +248,103 @@ const styles = StyleSheet.create({
export default App;
```
+
+
+
+```SnackPlayer name=flatlist-selectable&ext=tsx
+import React, {useState} from 'react';
+import {
+ FlatList,
+ SafeAreaView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+} from 'react-native';
+
+type ItemData = {
+ id: string;
+ title: string;
+};
+
+const DATA: ItemData[] = [
+ {
+ id: 'bd7acbea-c1b1-46c2-aed5-3ad53abb28ba',
+ title: 'First Item',
+ },
+ {
+ id: '3ac68afc-c605-48d3-a4f8-fbd91aa97f63',
+ title: 'Second Item',
+ },
+ {
+ id: '58694a0f-3da1-471f-bd96-145571e29d72',
+ title: 'Third Item',
+ },
+];
+
+type ItemProps = {
+ item: ItemData;
+ onPress: () => void;
+ backgroundColor: string;
+ textColor: string;
+};
+
+const Item = ({item, onPress, backgroundColor, textColor}: ItemProps) => (
+
+ {item.title}
+
+);
+
+const App = () => {
+ const [selectedId, setSelectedId] = useState();
+
+ const renderItem = ({item}: {item: ItemData}) => {
+ const backgroundColor = item.id === selectedId ? '#6e3b6e' : '#f9c2ff';
+ const color = item.id === selectedId ? 'white' : 'black';
+
+ return (
+ setSelectedId(item.id)}
+ backgroundColor={backgroundColor}
+ textColor={color}
+ />
+ );
+ };
+
+ return (
+
+ item.id}
+ extraData={selectedId}
+ />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: StatusBar.currentHeight || 0,
+ },
+ item: {
+ padding: 20,
+ marginVertical: 8,
+ marginHorizontal: 16,
+ },
+ title: {
+ fontSize: 32,
+ },
+});
+
+export default App;
+```
+
+
+
+
This is a convenience wrapper around [``](virtualizedlist.md), and thus inherits its props (as well as those of [``](scrollview.md)) that aren't explicitly listed here, along with the following caveats:
- Internal state is not preserved when content scrolls out of the render window. Make sure all your data is captured in the item data or external stores like Flux, Redux, or Relay.
@@ -180,8 +366,16 @@ Inherits [ScrollView Props](scrollview.md#props), unless it is nested in another
###
Required
**`renderItem`**
-```jsx
-renderItem({ item, index, separators });
+```tsx
+renderItem({
+ item: ItemT,
+ index: number,
+ separators: {
+ highlight: () => void;
+ unhighlight: () => void;
+ updateProps: (select: 'leading' | 'trailing', newProps: any) => void;
+ }
+}): JSX.Element;
```
Takes an item from `data` and renders it into the list.
@@ -203,27 +397,24 @@ Provides additional metadata like `index` if you need it, as well as a more gene
Example usage:
-```jsx
+```tsx
(
+ (({highlighted}) => (
))
}
- data={[{ title: 'Title Text', key: 'item1' }]}
- renderItem={({ item, index, separators }) => (
+ data={[{title: 'Title Text', key: 'item1'}]}
+ renderItem={({item, index, separators}) => (
this._onPress(item)}
onShowUnderlay={separators.highlight}
onHideUnderlay={separators.unhighlight}>
-
+ {item.title}
@@ -325,13 +516,13 @@ A marker property for telling the list to re-render (since it implements `PureCo
### `getItemLayout`
-```jsx
+```tsx
(data, index) => {length: number, offset: number, index: number}
```
`getItemLayout` is an optional optimization that allows skipping the measurement of dynamic content if you know the size (height or width) of items ahead of time. `getItemLayout` is efficient if you have fixed size items, for example:
-```jsx
+```tsx
getItemLayout={(data, index) => (
{length: ITEM_HEIGHT, offset: ITEM_HEIGHT * index, index}
)}
@@ -387,8 +578,8 @@ Reverses the direction of scroll. Uses scale transforms of `-1`.
### `keyExtractor`
-```jsx
-(item: object, index: number) => string;
+```tsx
+(item: ItemT, index: number) => string;
```
Used to extract a unique key for a given item at the specified index. Key is used for caching and as the react key to track item re-ordering. The default extractor checks `item.key`, then `item.id`, and then falls back to using the index, like React does.
@@ -411,8 +602,8 @@ Multiple columns can only be rendered with `horizontal={false}` and will zig-zag
### `onEndReached`
-```jsx
-(info: {distanceFromEnd: number}) => void
+```tsx
+(info: {distanceFromEnd: number}) => void;
```
Called once when the scroll position gets within `onEndReachedThreshold` of the rendered content.
@@ -435,8 +626,8 @@ How far from the end (in units of visible length of the list) the bottom edge of
### `onRefresh`
-```jsx
-() => void
+```tsx
+() => void;
```
If provided, a standard RefreshControl will be added for "Pull to Refresh" functionality. Make sure to also set the `refreshing` prop correctly.
@@ -451,9 +642,10 @@ If provided, a standard RefreshControl will be added for "Pull to Refresh" funct
Called when the viewability of rows changes, as defined by the `viewabilityConfig` prop.
-| Type |
-| ------------------------------------------------------------------------------------------------------------------ |
-| (callback: { changed: array of [ViewToken](viewtoken)s, viewableItems: array of [ViewToken](viewtoken)s }) => void |
+| Type |
+| ---- |
+
+| (callback: {changed: [ViewToken](viewtoken)[], viewableItems: [ViewToken](viewtoken)[]} => void;
---
@@ -512,7 +704,7 @@ At least one of the `viewAreaCoveragePercentThreshold` or `itemVisiblePercentThr
Error: Changing viewabilityConfig on the fly is not supported
```
-```jsx
+```tsx
constructor (props) {
super(props)
@@ -523,7 +715,7 @@ constructor (props) {
}
```
-```jsx
+```tsx
;
```
Provides a reference to the underlying scroll component
@@ -579,8 +771,8 @@ Provides a reference to the underlying scroll component
### `getScrollResponder()`
-```jsx
-getScrollResponder();
+```tsx
+getScrollResponder(): ScrollResponderMixin;
```
Provides a handle to the underlying scroll responder.
@@ -589,28 +781,16 @@ Provides a handle to the underlying scroll responder.
### `getScrollableNode()`
-```jsx
-getScrollableNode();
+```tsx
+getScrollableNode(): any;
```
Provides a handle to the underlying scroll node.
----
-
-### `recordInteraction()`
-
-```jsx
-recordInteraction();
-```
-
-Tells the list an interaction has occurred, which should trigger viewability calculations, e.g. if `waitForInteractions` is true and the user has not scrolled. This is typically called by taps on items or by navigation actions.
-
----
-
### `scrollToEnd()`
-```jsx
-scrollToEnd(params);
+```tsx
+scrollToEnd(params?: {animated?: boolean});
```
Scrolls to the end of the content. May be janky without `getItemLayout` prop.
@@ -629,8 +809,13 @@ Valid `params` keys are:
### `scrollToIndex()`
-```jsx
-scrollToIndex(params);
+```tsx
+scrollToIndex: (params: {
+ index: number;
+ animated?: boolean;
+ viewOffset?: number;
+ viewPosition?: number;
+});
```
Scrolls to the item at the specified index such that it is positioned in the viewable area such that `viewPosition` 0 places it at the top, 1 at the bottom, and 0.5 centered in the middle.
@@ -654,8 +839,12 @@ Valid `params` keys are:
### `scrollToItem()`
-```jsx
-scrollToItem(params);
+```tsx
+scrollToItem(params: {
+ animated?: ?boolean,
+ item: Item,
+ viewPosition?: number,
+});
```
Requires linear scan through data - use `scrollToIndex` instead if possible.
@@ -678,8 +867,11 @@ Valid `params` keys are:
### `scrollToOffset()`
-```jsx
-scrollToOffset(params);
+```tsx
+scrollToOffset(params: {
+ offset: number;
+ animated?: boolean;
+});
```
Scroll to a specific content pixel offset in the list.
diff --git a/docs/flexbox.md b/docs/flexbox.md
index f4b44da084c..c39fc3ae6b5 100644
--- a/docs/flexbox.md
+++ b/docs/flexbox.md
@@ -3,6 +3,8 @@ id: flexbox
title: Layout with Flexbox
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
A component can specify the layout of its children using the Flexbox algorithm. Flexbox is designed to provide a consistent layout on different screen sizes.
You will normally use a combination of `flexDirection`, `alignItems`, and `justifyContent` to achieve the right layout.
@@ -19,18 +21,22 @@ The defaults are different, with `flexDirection` defaulting to `column` instead
In the following example, the red, orange, and green views are all children in the container view that has `flex: 1` set. The red view uses `flex: 1` , the orange 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 orange `2/6` of the space, and the green `3/6` of the space.
```SnackPlayer name=Flex%20Example
-import React from "react";
-import { StyleSheet, Text, View } from "react-native";
+import React from 'react';
+import {StyleSheet, View} from 'react-native';
const Flex = () => {
return (
-
-
-
-
+
+
+
+
);
};
@@ -59,29 +65,25 @@ export default Flex;
You can learn more [here](https://yogalayout.com/docs/flex-direction).
-```SnackPlayer name=Flex%20Direction
-import React, { useState } from "react";
-import { StyleSheet, Text, TouchableOpacity, View } from "react-native";
+
+
+
+```SnackPlayer name=Flex%20Direction&ext=js
+import React, {useState} from 'react';
+import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
const FlexDirectionBasics = () => {
- const [flexDirection, setflexDirection] = useState("column");
+ const [flexDirection, setflexDirection] = useState('column');
return (
-
-
-
+ setSelectedValue={setflexDirection}>
+
+
+
);
};
@@ -93,32 +95,25 @@ const PreviewLayout = ({
selectedValue,
setSelectedValue,
}) => (
-
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
- style={[
- styles.button,
- selectedValue === value && styles.selected,
- ]}
- >
+ style={[styles.button, selectedValue === value && styles.selected]}>
+ ]}>
{value}
))}
-
- {children}
-
+ {children}
);
@@ -126,41 +121,41 @@ const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 8,
- backgroundColor: "aliceblue",
+ backgroundColor: 'aliceblue',
},
box: {
width: 50,
height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
- marginHorizontal: "1%",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
+ minWidth: '48%',
+ textAlign: 'center',
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
@@ -169,73 +164,63 @@ const styles = StyleSheet.create({
export default FlexDirectionBasics;
```
-## Layout Direction
-
-Layout [`direction`](layout-props#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 to 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 to the start of an element are applied on the right side.
+
+
-```SnackPlayer name=Flex%20Direction
-import React, { useState } from "react";
-import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
+```SnackPlayer name=Flex%20Direction&ext=tsx
+import React, {useState} from 'react';
+import {StyleSheet, Text, TouchableOpacity, View} from 'react-native';
+import type {PropsWithChildren} from 'react';
-const DirectionLayout = () => {
- const [direction, setDirection] = useState("ltr");
+const FlexDirectionBasics = () => {
+ const [flexDirection, setflexDirection] = useState('column');
return (
-
-
-
+ label="flexDirection"
+ values={['column', 'row', 'row-reverse', 'column-reverse']}
+ selectedValue={flexDirection}
+ setSelectedValue={setflexDirection}>
+
+
+
);
};
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: string[];
+ selectedValue: string;
+ setSelectedValue: (value: string) => void;
+}>;
+
const PreviewLayout = ({
label,
children,
values,
selectedValue,
setSelectedValue,
-}) => (
-
+}: PreviewLayoutProps) => (
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
- style={[
- styles.button,
- selectedValue === value && styles.selected,
- ]}
- >
+ style={[styles.button, selectedValue === value && styles.selected]}>
+ ]}>
{value}
))}
-
- {children}
-
+ {children}
);
@@ -243,97 +228,79 @@ const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 8,
- backgroundColor: "aliceblue",
+ backgroundColor: 'aliceblue',
},
box: {
width: 50,
height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
- marginHorizontal: "1%",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
+ minWidth: '48%',
+ textAlign: 'center',
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
});
-export default DirectionLayout;
+export default FlexDirectionBasics;
```
-## Justify Content
-
-[`justifyContent`](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.
+## Layout Direction
-- `space-between` Evenly space off children across the container's main axis, distributing the remaining space between the children.
+Layout [`direction`](layout-props#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.
-- `space-around` Evenly space off children across the container's main axis, distributing the 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.
+- `LTR` (**default value**) Text and children are laid out from left to right. Margin and padding applied to the start of an element are applied on the left side.
-- `space-evenly` Evenly distribute children 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.
+- `RTL` Text and children are laid out from right to left. Margin and padding applied to the start of an element are applied on the right side.
-You can learn more [here](https://yogalayout.com/docs/justify-content).
+
+
-```SnackPlayer name=Justify%20Content
-import React, { useState } from "react";
-import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
+```SnackPlayer name=Flex%20Direction&ext=js
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
-const JustifyContentBasics = () => {
- const [justifyContent, setJustifyContent] = useState("flex-start");
+const DirectionLayout = () => {
+ const [direction, setDirection] = useState('ltr');
return (
-
-
-
+ label="direction"
+ selectedValue={direction}
+ values={['ltr', 'rtl']}
+ setSelectedValue={setDirection}>
+
+
+
);
};
@@ -345,29 +312,25 @@ const PreviewLayout = ({
selectedValue,
setSelectedValue,
}) => (
-
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
- style={[styles.button, selectedValue === value && styles.selected]}
- >
+ style={[styles.button, selectedValue === value && styles.selected]}>
+ ]}>
{value}
))}
-
- {children}
-
+ {children}
);
@@ -375,153 +338,106 @@ const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 8,
- backgroundColor: "aliceblue",
+ backgroundColor: 'aliceblue',
},
box: {
width: 50,
height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
- marginHorizontal: "1%",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
+ minWidth: '48%',
+ textAlign: 'center',
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
});
-export default JustifyContentBasics;
+export default DirectionLayout;
```
-## Align Items
-
-[`alignItems`](layout-props#alignitems) describes how to align children along the cross axis of their container. It 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.
-
-:::info
-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.
-:::
-
-You can learn more [here](https://yogalayout.com/docs/align-items).
+
+
-```SnackPlayer name=Align%20Items
-import React, { useState } from "react";
-import {
- View,
- TouchableOpacity,
- Text,
- StyleSheet,
-} from "react-native";
+```SnackPlayer name=Flex%20Direction&ext=tsx
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
-const AlignItemsLayout = () => {
- const [alignItems, setAlignItems] = useState("stretch");
+const DirectionLayout = () => {
+ const [direction, setDirection] = useState('ltr');
return (
-
-
-
+ label="direction"
+ selectedValue={direction}
+ values={['ltr', 'rtl']}
+ setSelectedValue={setDirection}>
+
+
+
);
};
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: string[];
+ selectedValue: string;
+ setSelectedValue: (value: string) => void;
+}>;
+
const PreviewLayout = ({
label,
children,
values,
selectedValue,
setSelectedValue,
-}) => (
-
+}: PreviewLayoutProps) => (
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
- style={[
- styles.button,
- selectedValue === value && styles.selected,
- ]}
- >
+ style={[styles.button, selectedValue === value && styles.selected]}>
+ selectedValue === value && styles.selectedLabel,
+ ]}>
{value}
))}
-
- {children}
-
+ {children}
);
@@ -529,81 +445,96 @@ const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 8,
- backgroundColor: "aliceblue",
- minHeight: 200,
+ backgroundColor: 'aliceblue',
},
box: {
width: 50,
height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
- marginHorizontal: "1%",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
+ minWidth: '48%',
+ textAlign: 'center',
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
});
-export default AlignItemsLayout;
+export default DirectionLayout;
```
-## Align Self
+
+
-[`alignSelf`](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`.
+## Justify Content
-```SnackPlayer name=Align%20Self
-import React, { useState } from "react";
-import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
+[`justifyContent`](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`.
-const AlignSelfLayout = () => {
- const [alignSelf, setAlignSelf] = useState("stretch");
+- `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.
+
+- `space-between` Evenly space off children across the container's main axis, distributing the remaining space between the children.
+
+- `space-around` Evenly space off children across the container's main axis, distributing the 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 distribute children 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.
+
+You can learn more [here](https://yogalayout.com/docs/justify-content).
+
+
+
+
+```SnackPlayer name=Justify%20Content&ext=js
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+
+const JustifyContentBasics = () => {
+ const [justifyContent, setJustifyContent] = useState('flex-start');
return (
-
-
-
+ label="justifyContent"
+ selectedValue={justifyContent}
+ values={[
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'space-between',
+ 'space-around',
+ 'space-evenly',
+ ]}
+ setSelectedValue={setJustifyContent}>
+
+
+
);
};
@@ -615,33 +546,25 @@ const PreviewLayout = ({
selectedValue,
setSelectedValue,
}) => (
-
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
- style={[
- styles.button,
- selectedValue === value && styles.selected,
- ]}
- >
+ style={[styles.button, selectedValue === value && styles.selected]}>
+ selectedValue === value && styles.selectedLabel,
+ ]}>
{value}
))}
-
- {children}
-
+ {children}
);
@@ -649,244 +572,448 @@ const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 8,
- backgroundColor: "aliceblue",
- minHeight: 200,
+ backgroundColor: 'aliceblue',
},
box: {
width: 50,
height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
- marginHorizontal: "1%",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
+ minWidth: '48%',
+ textAlign: 'center',
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
});
-export default AlignSelfLayout;
+export default JustifyContentBasics;
```
-## Align Content
-
-[alignContent](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` (_default value when using Yoga on the web_) 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 cross axis, distributing the remaining space between the lines.
-
-- `space-around` Evenly space wrapped lines across the container's cross axis, distributing the remaining space around the lines. Compared to `space-between`, using `space-around` will result in space being distributed to the beginning of the first line and the end of the last line.
-
-You can learn more [here](https://yogalayout.com/docs/align-content).
+
+
-```SnackPlayer name=Align%20Content
-import React, { useState } from "react";
-import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
+```SnackPlayer name=Justify%20Content&ext=tsx
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
-const AlignContentLayout = () => {
- const [alignContent, setAlignContent] = useState("flex-start");
+const JustifyContentBasics = () => {
+ const [justifyContent, setJustifyContent] = useState('flex-start');
return (
-
-
-
-
-
-
-
+ setSelectedValue={setJustifyContent}>
+
+
+
);
};
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: string[];
+ selectedValue: string;
+ setSelectedValue: (value: string) => void;
+}>;
+
const PreviewLayout = ({
label,
children,
values,
selectedValue,
setSelectedValue,
-}) => (
-
+}: PreviewLayoutProps) => (
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
- style={[
- styles.button,
- selectedValue === value && styles.selected,
- ]}
- >
+ style={[styles.button, selectedValue === value && styles.selected]}>
+ selectedValue === value && styles.selectedLabel,
+ ]}>
{value}
))}
-
- {children}
-
+ {children}
);
const styles = StyleSheet.create({
container: {
flex: 1,
- flexWrap: "wrap",
marginTop: 8,
- backgroundColor: "aliceblue",
- maxHeight: 400,
+ backgroundColor: 'aliceblue',
},
box: {
width: 50,
- height: 80,
+ height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
- marginHorizontal: "1%",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
+ minWidth: '48%',
+ textAlign: 'center',
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
});
-export default AlignContentLayout;
+export default JustifyContentBasics;
```
-## Flex Wrap
+
+
-The [`flexWrap`](layout-props#flexwrap) property is set on containers and it 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.
+## Align Items
-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).
+[`alignItems`](layout-props#alignitems) describes how to align children along the cross axis of their container. It is very similar to `justifyContent` but instead of applying to the main axis, `alignItems` applies to the cross axis.
-```SnackPlayer name=Flex%20Wrap
-import React, { useState } from "react";
-import { View, TouchableOpacity, Text, StyleSheet } from "react-native";
+- `stretch` (**default value**) Stretch children of a container to match the `height` of the container's cross axis.
-const FlexWrapLayout = () => {
- const [flexWrap, setFlexWrap] = useState("wrap");
+- `flex-start` Align children of a container to the start of the container's cross axis.
- return (
-
-
-
-
-
-
+- `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.
+
+:::info
+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.
+:::
+
+You can learn more [here](https://yogalayout.com/docs/align-items).
+
+
+
+
+```SnackPlayer name=Align%20Items&ext=js
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+
+const AlignItemsLayout = () => {
+ const [alignItems, setAlignItems] = useState('stretch');
+
+ return (
+
+
+
+
+
+ );
+};
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ minHeight: 200,
+ },
+ box: {
+ width: 50,
+ height: 50,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default AlignItemsLayout;
+```
+
+
+
+
+```SnackPlayer name=Align%20Items&ext=tsx
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const AlignItemsLayout = () => {
+ const [alignItems, setAlignItems] = useState('stretch');
+
+ return (
+
+
+
+
+ );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: string[];
+ selectedValue: string;
+ setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}: PreviewLayoutProps) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ minHeight: 200,
+ },
+ box: {
+ width: 50,
+ height: 50,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default AlignItemsLayout;
+```
+
+
+
+
+## Align Self
+
+[`alignSelf`](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`.
+
+
+
+
+```SnackPlayer name=Align%20Self&ext=js
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+
+const AlignSelfLayout = () => {
+ const [alignSelf, setAlignSelf] = useState('stretch');
+
+ return (
+
+
+
);
};
@@ -898,123 +1025,882 @@ const PreviewLayout = ({
selectedValue,
setSelectedValue,
}) => (
-
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ minHeight: 200,
+ },
+ box: {
+ width: 50,
+ height: 50,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default AlignSelfLayout;
+```
+
+
+
+
+```SnackPlayer name=Align%20Self&ext=tsx
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+import type {FlexAlignType} from 'react-native';
+
+const AlignSelfLayout = () => {
+ const [alignSelf, setAlignSelf] = useState('stretch');
+
+ return (
+
+
+
+
+
+ );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: FlexAlignType[];
+ selectedValue: string;
+ setSelectedValue: (value: FlexAlignType) => void;
+}>;
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}: PreviewLayoutProps) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ minHeight: 200,
+ },
+ box: {
+ width: 50,
+ height: 50,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default AlignSelfLayout;
+```
+
+
+
+
+## Align Content
+
+[alignContent](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` (_default value when using Yoga on the web_) 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 cross axis, distributing the remaining space between the lines.
+
+- `space-around` Evenly space wrapped lines across the container's cross axis, distributing the remaining space around the lines. Compared to `space-between`, using `space-around` will result in space being distributed to the beginning of the first line and the end of the last line.
+
+You can learn more [here](https://yogalayout.com/docs/align-content).
+
+
+
+
+```SnackPlayer name=Align%20Content&ext=js
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+
+const AlignContentLayout = () => {
+ const [alignContent, setAlignContent] = useState('flex-start');
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ flexWrap: 'wrap',
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ maxHeight: 400,
+ },
+ box: {
+ width: 50,
+ height: 80,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default AlignContentLayout;
+```
+
+
+
+
+```SnackPlayer name=Align%20Content&ext=tsx
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const AlignContentLayout = () => {
+ const [alignContent, setAlignContent] = useState('flex-start');
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: string[];
+ selectedValue: string;
+ setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}: PreviewLayoutProps) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ flexWrap: 'wrap',
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ maxHeight: 400,
+ },
+ box: {
+ width: 50,
+ height: 80,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default AlignContentLayout;
+```
+
+
+
+
+## Flex Wrap
+
+The [`flexWrap`](layout-props#flexwrap) property is set on containers and it 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).
+
+
+
+
+```SnackPlayer name=Flex%20Wrap&ext=js
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+
+const FlexWrapLayout = () => {
+ const [flexWrap, setFlexWrap] = useState('wrap');
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ maxHeight: 400,
+ },
+ box: {
+ width: 50,
+ height: 80,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default FlexWrapLayout;
+```
+
+
+
+
+```SnackPlayer name=Flex%20Wrap&ext=tsx
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const FlexWrapLayout = () => {
+ const [flexWrap, setFlexWrap] = useState('wrap');
+
+ return (
+
+
+
+
+
+
+
+
+
+ );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: string[];
+ selectedValue: string;
+ setSelectedValue: (value: string) => void;
+}>;
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}: PreviewLayoutProps) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ maxHeight: 400,
+ },
+ box: {
+ width: 50,
+ height: 80,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default FlexWrapLayout;
+```
+
+
+
+
+## Flex Basis, Grow, and Shrink
+
+- [`flexBasis`](layout-props#flexbasis) is an axis-independent way of providing the default size of an item along the main axis. Setting the `flexBasis` 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 `flexBasis` of an item is the default size of that item, the size of the item before any `flexGrow` and `flexShrink` calculations are performed.
+
+- [`flexGrow`](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 childrenâs `flexGrow` values.
+
+- [`flexShrink`](layout-props#flexshrink) describes how to shrink children along the main axis in the case in which the total size of the children overflows the size of the container on the main axis. `flexShrink` is very similar to `flexGrow` 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.
+
+ `flexShrink` accepts any floating point value >= 0, with 0 being the default value (on the web, the default is 1). A container will shrink its children weighted by the childrenâs `flexShrink` values.
+
+You can learn more [here](https://yogalayout.com/docs/flex).
+
+
+
+
+```SnackPlayer name=Flex%20Basis%2C%20Grow%2C%20and%20Shrink&ext=js
+import React, {useState} from 'react';
+import {View, Text, TextInput, StyleSheet} from 'react-native';
+
+const App = () => {
+ const [powderblue, setPowderblue] = useState({
+ flexGrow: 0,
+ flexShrink: 1,
+ flexBasis: 'auto',
+ });
+ const [skyblue, setSkyblue] = useState({
+ flexGrow: 1,
+ flexShrink: 0,
+ flexBasis: 100,
+ });
+ const [steelblue, setSteelblue] = useState({
+ flexGrow: 0,
+ flexShrink: 1,
+ flexBasis: 200,
+ });
+ return (
+
+
+
+
+
+
+
+
-
- {value}
-
-
- ))}
+ />
+
+
+
+ );
+};
+
+const BoxInfo = ({color, flexBasis, flexShrink, setStyle, flexGrow}) => (
+
- {children}
+ styles.boxLabel,
+ {
+ backgroundColor: color,
+ },
+ ]}>
+
+ Box
+
+ flexBasis
+
+ setStyle(value => ({
+ ...value,
+ flexBasis: isNaN(parseInt(fB, 10)) ? 'auto' : parseInt(fB, 10),
+ }))
+ }
+ />
+ flexShrink
+
+ setStyle(value => ({
+ ...value,
+ flexShrink: isNaN(parseInt(fS, 10)) ? undefined : parseInt(fS, 10),
+ }))
+ }
+ />
+ flexGrow
+
+ setStyle(value => ({
+ ...value,
+ flexGrow: isNaN(parseInt(fG, 10)) ? undefined : parseInt(fG, 10),
+ }))
+ }
+ />
);
const styles = StyleSheet.create({
container: {
flex: 1,
- marginTop: 8,
- backgroundColor: "aliceblue",
- maxHeight: 400,
+ paddingHorizontal: 10,
},
box: {
+ flex: 1,
+ height: 50,
width: 50,
- height: 80,
},
- row: {
- flexDirection: "row",
- flexWrap: "wrap",
- },
- button: {
- paddingHorizontal: 8,
- paddingVertical: 6,
+ boxLabel: {
+ minWidth: 80,
+ padding: 8,
borderRadius: 4,
- backgroundColor: "oldlace",
- marginHorizontal: "1%",
- marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
- },
- selected: {
- backgroundColor: "coral",
- borderWidth: 0,
+ marginTop: 8,
},
- buttonLabel: {
- fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ label: {
+ marginTop: 6,
+ fontSize: 16,
+ fontWeight: '100',
},
- selectedLabel: {
- color: "white",
+ previewContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ backgroundColor: 'aliceblue',
},
- label: {
- textAlign: "center",
+ row: {
+ flex: 1,
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ alignItems: 'center',
marginBottom: 10,
- fontSize: 24,
+ },
+ input: {
+ borderBottomWidth: 1,
+ paddingVertical: 3,
+ width: 50,
+ textAlign: 'center',
},
});
-export default FlexWrapLayout;
+export default App;
```
-## Flex Basis, Grow, and Shrink
-
-- [`flexBasis`](layout-props#flexbasis) is an axis-independent way of providing the default size of an item along the main axis. Setting the `flexBasis` 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 `flexBasis` of an item is the default size of that item, the size of the item before any `flexGrow` and `flexShrink` calculations are performed.
-
-- [`flexGrow`](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 childrenâs `flexGrow` values.
-
-- [`flexShrink`](layout-props#flexshrink) describes how to shrink children along the main axis in the case in which the total size of the children overflows the size of the container on the main axis. `flexShrink` is very similar to `flexGrow` 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.
-
- `flexShrink` accepts any floating point value >= 0, with 0 being the default value (on the web, the default is 1). A container will shrink its children weighted by the childrenâs `flexShrink` values.
-
-You can learn more [here](https://yogalayout.com/docs/flex).
+
+
-```SnackPlayer name=Flex%20Basis%2C%20Grow%2C%20and%20Shrink
-import React, { useState } from "react";
-import {
- View,
- Text,
- TextInput,
- StyleSheet,
-} from "react-native";
+```SnackPlayer name=Flex%20Basis%2C%20Grow%2C%20and%20Shrink&ext=tsx
+import React, {useState} from 'react';
+import {View, Text, TextInput, StyleSheet} from 'react-native';
+import type {ViewStyle} from 'react-native';
const App = () => {
- const [powderblue, setPowderblue] = useState({
+ const [powderblue, setPowderblue] = useState({
flexGrow: 0,
flexShrink: 1,
- flexBasis: "auto",
+ flexBasis: 'auto',
});
- const [skyblue, setSkyblue] = useState({
+ const [skyblue, setSkyblue] = useState({
flexGrow: 1,
flexShrink: 0,
flexBasis: 100,
});
- const [steelblue, setSteelblue] = useState({
+ const [steelblue, setSteelblue] = useState({
flexGrow: 0,
flexShrink: 1,
flexBasis: 200,
@@ -1025,26 +1911,13 @@ const App = () => {
style={[
styles.container,
{
- flexDirection: "row",
- alignContent: "space-between",
+ flexDirection: 'row',
+ alignContent: 'space-between',
},
- ]}
- >
-
-
-
+ ]}>
+
+
+ {
flexBasis: powderblue.flexBasis,
flexGrow: powderblue.flexGrow,
flexShrink: powderblue.flexShrink,
- backgroundColor: "powderblue",
+ backgroundColor: 'powderblue',
},
]}
/>
@@ -1065,7 +1938,7 @@ const App = () => {
flexBasis: skyblue.flexBasis,
flexGrow: skyblue.flexGrow,
flexShrink: skyblue.flexShrink,
- backgroundColor: "skyblue",
+ backgroundColor: 'skyblue',
},
]}
/>
@@ -1076,7 +1949,7 @@ const App = () => {
flexBasis: steelblue.flexBasis,
flexGrow: steelblue.flexGrow,
flexShrink: steelblue.flexShrink,
- backgroundColor: "steelblue",
+ backgroundColor: 'steelblue',
},
]}
/>
@@ -1085,68 +1958,65 @@ const App = () => {
);
};
+type BoxInfoProps = ViewStyle & {
+ color: string;
+ setStyle: React.Dispatch>;
+};
+
const BoxInfo = ({
color,
flexBasis,
flexShrink,
setStyle,
flexGrow,
-}) => (
-
+}: BoxInfoProps) => (
+
+ ]}>
+ color: '#fff',
+ fontWeight: '500',
+ textAlign: 'center',
+ }}>
Box
flexBasis
- setStyle((value) => ({
+ onChangeText={fB =>
+ setStyle(value => ({
...value,
- flexBasis: isNaN(parseInt(fB))
- ? "auto"
- : parseInt(fB),
+ flexBasis: isNaN(parseInt(fB, 10)) ? 'auto' : parseInt(fB, 10),
}))
}
/>
flexShrink
- setStyle((value) => ({
+ onChangeText={fS =>
+ setStyle(value => ({
...value,
- flexShrink: isNaN(parseInt(fS))
- ? ""
- : parseInt(fS),
+ flexShrink: isNaN(parseInt(fS, 10)) ? undefined : parseInt(fS, 10),
}))
}
/>
flexGrow
- setStyle((value) => ({
+ onChangeText={fG =>
+ setStyle(value => ({
...value,
- flexGrow: isNaN(parseInt(fG))
- ? ""
- : parseInt(fG),
+ flexGrow: isNaN(parseInt(fG, 10)) ? undefined : parseInt(fG, 10),
}))
}
/>
@@ -1159,44 +2029,272 @@ const styles = StyleSheet.create({
paddingHorizontal: 10,
},
box: {
- flex: 1,
- height: 50,
+ flex: 1,
+ height: 50,
+ width: 50,
+ },
+ boxLabel: {
+ minWidth: 80,
+ padding: 8,
+ borderRadius: 4,
+ marginTop: 8,
+ },
+ label: {
+ marginTop: 6,
+ fontSize: 16,
+ fontWeight: '100',
+ },
+ previewContainer: {
+ flex: 1,
+ flexDirection: 'row',
+ backgroundColor: 'aliceblue',
+ },
+ row: {
+ flex: 1,
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ alignItems: 'center',
+ marginBottom: 10,
+ },
+ input: {
+ borderBottomWidth: 1,
+ paddingVertical: 3,
+ width: 50,
+ textAlign: 'center',
+ },
+});
+
+export default App;
+```
+
+
+
+
+## Row Gap, Column Gap and Gap
+
+- [`rowGap`](layout-props#rowgap) sets the size of the gap (gutter) between an element's rows.
+
+- [`columnGap`](layout-props#columngap) sets the size of the gap (gutter) between an element's columns.
+
+- [`gap`](layout-props#gap) sets the size of the gap (gutter) between rows and columns. It is a shorthand for `rowGap` and `columnGap`.
+
+You can use `flexWrap` and `alignContent` alongwith `gap` to add consistent spacing between items.
+
+
+
+
+```SnackPlayer name=Row%20Gap%20and%20Column%20Gap&ext=js
+import React, {useState} from 'react';
+import {View, Text, StyleSheet, TextInput} from 'react-native';
+
+const RowGapAndColumnGap = () => {
+ const [rowGap, setRowGap] = useState(10);
+ const [columnGap, setColumnGap] = useState(10);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+const PreviewLayout = ({
+ children,
+ handleColumnGapChange,
+ handleRowGapChange,
+ rowGap,
+ columnGap,
+}) => (
+
+
+
+ Row Gap
+ handleRowGapChange(Number(v))}
+ />
+
+
+ Column Gap
+ handleColumnGapChange(Number(v))}
+ />
+
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ itemsCenter: {alignItems: 'center'},
+ inputContainer: {
+ gap: 4,
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ },
+ previewContainer: {padding: 10, flex: 1},
+ input: {
+ borderBottomWidth: 1,
+ paddingVertical: 3,
+ width: 50,
+ textAlign: 'center',
+ },
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ maxHeight: 400,
+ flexWrap: 'wrap',
+ alignContent: 'flex-start',
+ },
+ box: {
+ width: 50,
+ height: 80,
+ },
+ box1: {
+ backgroundColor: 'orangered',
+ },
+ box2: {
+ backgroundColor: 'orange',
+ },
+ box3: {
+ backgroundColor: 'mediumseagreen',
+ },
+ box4: {
+ backgroundColor: 'deepskyblue',
+ },
+ box5: {
+ backgroundColor: 'mediumturquoise',
+ },
+});
+
+export default RowGapAndColumnGap;
+```
+
+
+
+
+```SnackPlayer name=Row%20Gap%20and%20Column%20Gap&ext=tsx
+import React, {useState} from 'react';
+import {View, Text, StyleSheet, TextInput} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const RowGapAndColumnGap = () => {
+ const [rowGap, setRowGap] = useState(10);
+ const [columnGap, setColumnGap] = useState(10);
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+ columnGap: number;
+ handleColumnGapChange: (gap: number) => void;
+ rowGap: number;
+ handleRowGapChange: (gap: number) => void;
+}>;
+
+const PreviewLayout = ({
+ children,
+ handleColumnGapChange,
+ handleRowGapChange,
+ rowGap,
+ columnGap,
+}: PreviewLayoutProps) => (
+
+
+
+ Row Gap
+ handleRowGapChange(Number(v))}
+ />
+
+
+ Column Gap
+ handleColumnGapChange(Number(v))}
+ />
+
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ itemsCenter: {alignItems: 'center'},
+ inputContainer: {
+ gap: 4,
+ flexDirection: 'row',
+ justifyContent: 'space-around',
+ },
+ previewContainer: {padding: 10, flex: 1},
+ input: {
+ borderBottomWidth: 1,
+ paddingVertical: 3,
+ width: 50,
+ textAlign: 'center',
+ },
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ maxHeight: 400,
+ flexWrap: 'wrap',
+ alignContent: 'flex-start',
+ },
+ box: {
width: 50,
+ height: 80,
},
- boxLabel: {
- minWidth: 80,
- padding: 8,
- borderRadius: 4,
- marginTop: 8,
+ box1: {
+ backgroundColor: 'orangered',
},
- label: {
- marginTop: 6,
- fontSize: 16,
- fontWeight: "100",
+ box2: {
+ backgroundColor: 'orange',
},
- previewContainer: {
- flex: 1,
- flexDirection: "row",
- backgroundColor: "aliceblue",
+ box3: {
+ backgroundColor: 'mediumseagreen',
},
- row: {
- flex: 1,
- flexDirection: "row",
- flexWrap: "wrap",
- alignItems: "center",
- marginBottom: 10,
+ box4: {
+ backgroundColor: 'deepskyblue',
},
- input: {
- borderBottomWidth: 1,
- paddingVertical: 3,
- width: 50,
- textAlign: "center",
+ box5: {
+ backgroundColor: 'mediumturquoise',
},
});
-export default App;
+export default RowGapAndColumnGap;
```
+
+
+
## Width and Height
The `width` property specifies the width of an element's content area. Similarly, the `height` property specifies the height of an element's content area.
@@ -1209,56 +2307,42 @@ Both `width` and `height` can take the following values:
- `percentage` Defines the width or height in percentage of its parent's width or height, respectively.
-```SnackPlayer name=Width%20and%20Height
-import React, { useState } from "react";
+
+
+
+```SnackPlayer name=Width%20and%20Height&ext=js
+import React, {useState} from 'react';
import {
View,
SafeAreaView,
TouchableOpacity,
Text,
StyleSheet,
-} from "react-native";
+} from 'react-native';
const WidthHeightBasics = () => {
- const [widthType, setWidthType] = useState("auto");
- const [heightType, setHeightType] = useState("auto");
+ const [widthType, setWidthType] = useState('auto');
+ const [heightType, setHeightType] = useState('auto');
return (
+ setHeightType={setHeightType}>
-
-
-
+ }}>
+
+
+
);
@@ -1273,24 +2357,19 @@ const PreviewLayout = ({
setWidthType,
setHeightType,
}) => (
-
+ width
- {widthValues.map((value) => (
+ {widthValues.map(value => (
setWidthType(value)}
- style={[
- styles.button,
- widthType === value && styles.selected,
- ]}
- >
+ style={[styles.button, widthType === value && styles.selected]}>
+ ]}>
{value}
@@ -1298,21 +2377,157 @@ const PreviewLayout = ({
height
- {heightValues.map((value) => (
+ {heightValues.map(value => (
setHeightType(value)}
- style={[
- styles.button,
- heightType === value && styles.selected,
- ]}
- >
+ style={[styles.button, heightType === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ box: {
+ width: 50,
+ height: 50,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ padding: 8,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginRight: 10,
+ marginBottom: 10,
+ },
+ selected: {
+ backgroundColor: 'coral',
+ shadowOpacity: 0,
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default WidthHeightBasics;
+```
+
+
+
+
+```SnackPlayer name=Width%20and%20Height&ext=tsx
+import React, {useState} from 'react';
+import {
+ View,
+ SafeAreaView,
+ TouchableOpacity,
+ Text,
+ StyleSheet,
+} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+type Dimension = string | number;
+
+const WidthHeightBasics = () => {
+ const [widthType, setWidthType] = useState('auto');
+ const [heightType, setHeightType] = useState('auto');
+
+ return (
+
+
+
+
+
+
+
+ );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+ widthType: Dimension;
+ heightType: Dimension;
+ widthValues: Dimension[];
+ heightValues: Dimension[];
+ setWidthType: (value: Dimension) => void;
+ setHeightType: (value: Dimension) => void;
+}>;
+
+const PreviewLayout = ({
+ children,
+ widthType,
+ heightType,
+ widthValues,
+ heightValues,
+ setWidthType,
+ setHeightType,
+}: PreviewLayoutProps) => (
+
+
+ width
+ {widthValues.map(value => (
+ setWidthType(value)}
+ style={[styles.button, widthType === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+
+ height
+ {heightValues.map(value => (
+ setHeightType(value)}
+ style={[styles.button, heightType === value && styles.selected]}>
+ ]}>
{value}
@@ -1328,32 +2543,32 @@ const styles = StyleSheet.create({
height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
padding: 8,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
marginRight: 10,
marginBottom: 10,
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
shadowOpacity: 0,
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
@@ -1362,6 +2577,9 @@ const styles = StyleSheet.create({
export default WidthHeightBasics;
```
+
+
+
## Absolute & Relative Layout
The `position` type of an element defines how it is positioned within its parent.
@@ -1370,26 +2588,22 @@ The `position` type of an element defines how it is positioned within its parent
- `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.
-```SnackPlayer name=Absolute%20%26%20Relative%20Layout
-import React, { useState } from "react";
-import {
- View,
- SafeAreaView,
- TouchableOpacity,
- Text,
- StyleSheet,
-} from "react-native";
+
+
+
+```SnackPlayer name=Absolute%20%26%20Relative%20Layout&ext=js
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
const PositionLayout = () => {
- const [position, setPosition] = useState("relative");
+ const [position, setPosition] = useState('relative');
return (
+ values={['relative', 'absolute']}
+ setSelectedValue={setPosition}>
{
top: 25,
left: 25,
position,
- backgroundColor: "powderblue",
+ backgroundColor: 'powderblue',
},
]}
/>
@@ -1408,7 +2622,7 @@ const PositionLayout = () => {
top: 50,
left: 50,
position,
- backgroundColor: "skyblue",
+ backgroundColor: 'skyblue',
},
]}
/>
@@ -1419,7 +2633,7 @@ const PositionLayout = () => {
top: 75,
left: 75,
position,
- backgroundColor: "steelblue",
+ backgroundColor: 'steelblue',
},
]}
/>
@@ -1434,25 +2648,157 @@ const PreviewLayout = ({
selectedValue,
setSelectedValue,
}) => (
-
+ {label}
- {values.map((value) => (
+ {values.map(value => (
setSelectedValue(value)}
- style={[
- styles.button,
- selectedValue === value && styles.selected,
- ]}
- >
+ style={[styles.button, selectedValue === value && styles.selected]}>
+
+ {value}
+
+
+ ))}
+
+ {children}
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: 8,
+ backgroundColor: 'aliceblue',
+ minHeight: 200,
+ },
+ box: {
+ width: 50,
+ height: 50,
+ },
+ row: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ button: {
+ paddingHorizontal: 8,
+ paddingVertical: 6,
+ borderRadius: 4,
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
+ marginBottom: 6,
+ minWidth: '48%',
+ textAlign: 'center',
+ },
+ selected: {
+ backgroundColor: 'coral',
+ borderWidth: 0,
+ },
+ buttonLabel: {
+ fontSize: 12,
+ fontWeight: '500',
+ color: 'coral',
+ },
+ selectedLabel: {
+ color: 'white',
+ },
+ label: {
+ textAlign: 'center',
+ marginBottom: 10,
+ fontSize: 24,
+ },
+});
+
+export default PositionLayout;
+```
+
+
+
+
+```SnackPlayer name=Absolute%20%26%20Relative%20Layout&ext=tsx
+import React, {useState} from 'react';
+import {View, TouchableOpacity, Text, StyleSheet} from 'react-native';
+import type {PropsWithChildren} from 'react';
+
+const PositionLayout = () => {
+ const [position, setPosition] = useState<'relative' | 'absolute'>('relative');
+
+ return (
+
+
+
+
+
+ );
+};
+
+type PreviewLayoutProps = PropsWithChildren<{
+ label: string;
+ values: Array<'relative' | 'absolute'>;
+ selectedValue: string;
+ setSelectedValue: (value: 'relative' | 'absolute') => void;
+}>;
+
+const PreviewLayout = ({
+ label,
+ children,
+ values,
+ selectedValue,
+ setSelectedValue,
+}: PreviewLayoutProps) => (
+
+ {label}
+
+ {values.map(value => (
+ setSelectedValue(value)}
+ style={[styles.button, selectedValue === value && styles.selected]}>
+ selectedValue === value && styles.selectedLabel,
+ ]}>
{value}
@@ -1466,7 +2812,7 @@ const styles = StyleSheet.create({
container: {
flex: 1,
marginTop: 8,
- backgroundColor: "aliceblue",
+ backgroundColor: 'aliceblue',
minHeight: 200,
},
box: {
@@ -1474,34 +2820,34 @@ const styles = StyleSheet.create({
height: 50,
},
row: {
- flexDirection: "row",
- flexWrap: "wrap",
+ flexDirection: 'row',
+ flexWrap: 'wrap',
},
button: {
paddingHorizontal: 8,
paddingVertical: 6,
borderRadius: 4,
- backgroundColor: "oldlace",
- alignSelf: "flex-start",
- marginHorizontal: "1%",
+ backgroundColor: 'oldlace',
+ alignSelf: 'flex-start',
+ marginHorizontal: '1%',
marginBottom: 6,
- minWidth: "48%",
- textAlign: "center",
+ minWidth: '48%',
+ textAlign: 'center',
},
selected: {
- backgroundColor: "coral",
+ backgroundColor: 'coral',
borderWidth: 0,
},
buttonLabel: {
fontSize: 12,
- fontWeight: "500",
- color: "coral",
+ fontWeight: '500',
+ color: 'coral',
},
selectedLabel: {
- color: "white",
+ color: 'white',
},
label: {
- textAlign: "center",
+ textAlign: 'center',
marginBottom: 10,
fontSize: 24,
},
@@ -1510,6 +2856,9 @@ const styles = StyleSheet.create({
export default PositionLayout;
```
+
+
+
## Going Deeper
Check out the interactive [yoga playground](https://yogalayout.com/playground) that you can use to get a better understanding of flexbox.
diff --git a/docs/gesture-responder-system.md b/docs/gesture-responder-system.md
index ed29d81c7ca..e30fc80373c 100644
--- a/docs/gesture-responder-system.md
+++ b/docs/gesture-responder-system.md
@@ -24,20 +24,20 @@ The responder system can be complicated to use. So we have provided an abstract
A view can become the touch responder by implementing the correct negotiation methods. There are two methods to ask the view if it wants to become responder:
-- `View.props.onStartShouldSetResponder: (evt) => true,` - Does this view want to become responder on the start of a touch?
-- `View.props.onMoveShouldSetResponder: (evt) => true,` - Called for every touch move on the View when it is not the responder: does this view want to "claim" touch responsiveness?
+- `View.props.onStartShouldSetResponder: evt => true,` - Does this view want to become responder on the start of a touch?
+- `View.props.onMoveShouldSetResponder: evt => true,` - Called for every touch move on the View when it is not the responder: does this view want to "claim" touch responsiveness?
If the View returns true and attempts to become the responder, one of the following will happen:
-- `View.props.onResponderGrant: (evt) => {}` - The View is now responding for touch events. This is the time to highlight and show the user what is happening
-- `View.props.onResponderReject: (evt) => {}` - Something else is the responder right now and will not release it
+- `View.props.onResponderGrant: evt => {}` - The View is now responding for touch events. This is the time to highlight and show the user what is happening
+- `View.props.onResponderReject: evt => {}` - Something else is the responder right now and will not release it
If the view is responding, the following handlers can be called:
-- `View.props.onResponderMove: (evt) => {}` - The user is moving their finger
-- `View.props.onResponderRelease: (evt) => {}` - Fired at the end of the touch, ie "touchUp"
-- `View.props.onResponderTerminationRequest: (evt) => true` - Something else wants to become responder. Should this view release the responder? Returning true allows release
-- `View.props.onResponderTerminate: (evt) => {}` - The responder has been taken from the View. Might be taken by other views after a call to `onResponderTerminationRequest`, or might be taken by the OS without asking (happens with control center/ notification center on iOS)
+- `View.props.onResponderMove: evt => {}` - The user is moving their finger
+- `View.props.onResponderRelease: evt => {}` - Fired at the end of the touch, ie "touchUp"
+- `View.props.onResponderTerminationRequest: evt => true` - Something else wants to become responder. Should this view release the responder? Returning true allows release
+- `View.props.onResponderTerminate: evt => {}` - The responder has been taken from the View. Might be taken by other views after a call to `onResponderTerminationRequest`, or might be taken by the OS without asking (happens with control center/ notification center on iOS)
`evt` is a synthetic touch event with the following form:
@@ -58,8 +58,8 @@ If the view is responding, the following handlers can be called:
However, sometimes a parent will want to make sure that it becomes responder. This can be handled by using the capture phase. Before the responder system bubbles up from the deepest component, it will do a capture phase, firing `on*ShouldSetResponderCapture`. So if a parent View wants to prevent the child from becoming responder on a touch start, it should have a `onStartShouldSetResponderCapture` handler which returns true.
-- `View.props.onStartShouldSetResponderCapture: (evt) => true,`
-- `View.props.onMoveShouldSetResponderCapture: (evt) => true,`
+- `View.props.onStartShouldSetResponderCapture: evt => true,`
+- `View.props.onMoveShouldSetResponderCapture: evt => true,`
### PanResponder
diff --git a/docs/getting-started.md b/docs/getting-started.md
index 7146a639dd2..ea3b70a6fcf 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -26,7 +26,7 @@ Run the following command to create a new React Native project called "AwesomePr
npx create-expo-app AwesomeProject
cd AwesomeProject
-npm start # you can also use: npx expo start
+npx expo start
```
@@ -36,7 +36,7 @@ npm start # you can also use: npx expo start
yarn create expo-app AwesomeProject
cd AwesomeProject
-yarn start # you can also use: yarn expo start
+yarn expo start
```
diff --git a/docs/handling-text-input.md b/docs/handling-text-input.md
index e150e5f0091..e94f6ef4cd5 100644
--- a/docs/handling-text-input.md
+++ b/docs/handling-text-input.md
@@ -8,8 +8,8 @@ title: 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 name=Handling%20Text%20Input
-import React, { useState } from 'react';
-import { Text, TextInput, View } from 'react-native';
+import React, {useState} from 'react';
+import {Text, TextInput, View} from 'react-native';
const PizzaTranslator = () => {
const [text, setText] = useState('');
@@ -22,11 +22,14 @@ const PizzaTranslator = () => {
defaultValue={text}
/>
- {text.split(' ').map((word) => word && 'đ').join(' ')}
+ {text
+ .split(' ')
+ .map(word => word && 'đ')
+ .join(' ')}
);
-}
+};
export default PizzaTranslator;
```
diff --git a/docs/handling-touches.md b/docs/handling-touches.md
index c339e976e07..472bcfb816b 100644
--- a/docs/handling-touches.md
+++ b/docs/handling-touches.md
@@ -9,10 +9,10 @@ Users interact with mobile apps mainly through touch. They can use a combination
[Button](button.md) provides a basic button component that is rendered nicely on all platforms. The minimal example to display a button looks like this:
-```jsx
+```tsx
{
- alert('You tapped the button!');
+ consoele.log('You tapped the button!');
}}
title="Press Me"
/>
@@ -25,22 +25,19 @@ This will render a blue label on iOS, and a blue rounded rectangle with light te
Go ahead and play around with the `Button` component using the example below. You can select which platform your app is previewed in by clicking on the toggle in the bottom right and then clicking on "Tap to Play" to preview the app.
```SnackPlayer name=Button%20Basics
-import React, { Component } from 'react';
-import { Button, StyleSheet, View } from 'react-native';
+import React, {Component} from 'react';
+import {Alert, Button, StyleSheet, View} from 'react-native';
export default class ButtonBasics extends Component {
_onPressButton() {
- alert('You tapped the button!')
+ Alert.alert('You tapped the button!');
}
render() {
return (
-
+
-
-
+
+
);
@@ -67,17 +57,17 @@ export default class ButtonBasics extends Component {
const styles = StyleSheet.create({
container: {
- flex: 1,
- justifyContent: 'center',
+ flex: 1,
+ justifyContent: 'center',
},
buttonContainer: {
- margin: 20
+ margin: 20,
},
alternativeLayoutButtonContainer: {
margin: 20,
flexDirection: 'row',
- justifyContent: 'space-between'
- }
+ justifyContent: 'space-between',
+ },
});
```
@@ -100,19 +90,28 @@ In some cases, you may want to detect when a user presses and holds a view for a
Let's see all of these in action:
```SnackPlayer name=Touchables
-import React, { Component } from 'react';
-import { Platform, StyleSheet, Text, TouchableHighlight, TouchableOpacity, TouchableNativeFeedback, TouchableWithoutFeedback, View } from 'react-native';
+import React, {Component} from 'react';
+import {
+ Alert,
+ Platform,
+ StyleSheet,
+ Text,
+ TouchableHighlight,
+ TouchableOpacity,
+ TouchableNativeFeedback,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
export default class Touchables extends Component {
_onPressButton() {
- alert('You tapped the button!')
+ Alert.alert('You tapped the button!');
}
_onLongPressButton() {
- alert('You long-pressed the button!')
+ Alert.alert('You long-pressed the button!');
}
-
render() {
return (
@@ -127,20 +126,28 @@ export default class Touchables extends Component {
+ onPress={this._onPressButton}
+ background={
+ Platform.OS === 'android'
+ ? TouchableNativeFeedback.SelectableBackground()
+ : undefined
+ }>
- TouchableNativeFeedback {Platform.OS !== 'android' ? '(Android only)' : ''}
+
+ TouchableNativeFeedback{' '}
+ {Platform.OS !== 'android' ? '(Android only)' : ''}
+
-
+ TouchableWithoutFeedback
-
+ Touchable with Long Press
@@ -153,19 +160,19 @@ export default class Touchables extends Component {
const styles = StyleSheet.create({
container: {
paddingTop: 60,
- alignItems: 'center'
+ alignItems: 'center',
},
button: {
marginBottom: 30,
width: 260,
alignItems: 'center',
- backgroundColor: '#2196F3'
+ backgroundColor: '#2196F3',
},
buttonText: {
textAlign: 'center',
padding: 20,
- color: 'white'
- }
+ color: 'white',
+ },
});
```
diff --git a/docs/headless-js-android.md b/docs/headless-js-android.md
index 10c712c4a55..182ea307bb5 100644
--- a/docs/headless-js-android.md
+++ b/docs/headless-js-android.md
@@ -12,17 +12,17 @@ Headless JS is a way to run tasks in JavaScript while your app is in the backgro
A task is an async function that you register on `AppRegistry`, similar to registering React applications:
-```jsx
-import { AppRegistry } from 'react-native';
+```tsx
+import {AppRegistry} from 'react-native';
AppRegistry.registerHeadlessTask('SomeTaskName', () =>
- require('SomeTaskName')
+ require('SomeTaskName'),
);
```
Then, in `SomeTaskName.js`:
-```jsx
-module.exports = async (taskData) => {
+```tsx
+module.exports = async taskData => {
// do stuff
};
```
@@ -178,10 +178,10 @@ A retry attempt will only be made when a specific `Error` is thrown. Inside a he
Example:
-```jsx
+```tsx
import {HeadlessJsTaskError} from 'HeadlessJsTask';
-module.exports = async (taskData) => {
+module.exports = async taskData => {
const condition = ...;
if (!condition) {
throw new HeadlessJsTaskError();
diff --git a/docs/height-and-width.md b/docs/height-and-width.md
index 2319c44dd48..485667831cd 100644
--- a/docs/height-and-width.md
+++ b/docs/height-and-width.md
@@ -11,20 +11,32 @@ The general way to set the dimensions of a component is by adding a fixed `width
```SnackPlayer name=Height%20and%20Width
import React from 'react';
-import { View } from 'react-native';
+import {View} from 'react-native';
const FixedDimensionsBasics = () => {
return (
-
-
-
+
+
+
);
};
@@ -48,17 +60,17 @@ A component can only expand to fill available space if its parent has dimensions
```SnackPlayer name=Flex%20Dimensions
import React from 'react';
-import { View } from 'react-native';
+import {View} from 'react-native';
const FlexDimensionsBasics = () => {
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`?
-
-
-
-
+
+
+
+
);
};
@@ -74,22 +86,33 @@ If you want to fill a certain portion of the screen, but you _don't_ want to use
```SnackPlayer name=Percentage%20Dimensions
import React from 'react';
-import { View } from 'react-native';
+import {View} from 'react-native';
const PercentageDimensionsBasics = () => {
// Try removing the `height: '100%'` on the parent View.
// The parent will not have dimensions, so the children can't expand.
return (
-
-
-
-
+
+
+
+
);
};
diff --git a/docs/hermes.md b/docs/hermes.md
index 553e74e803d..6b661126a64 100644
--- a/docs/hermes.md
+++ b/docs/hermes.md
@@ -3,23 +3,21 @@ id: hermes
title: Using Hermes
---
-import M1Cocoapods from './\_markdown-m1-cocoapods.mdx';
-
-[Hermes](https://hermesengine.dev) is an open-source JavaScript engine optimized for React Native. For many apps, enabling Hermes will result in improved start-up time, decreased memory usage, and smaller app size.
-As of React Native 0.70, Hermes is the default engine and no additional configuration is required to enable it.
+[Hermes](https://hermesengine.dev) is an open-source JavaScript engine optimized for React Native. For many apps, using Hermes will result in improved start-up time, decreased memory usage, and smaller app size when compared to JavaScriptCore.
+Hermes is used by default by React Native and no additional configuration is required to enable it.
## Bundled Hermes
-Starting with React Native 0.69.0, every version of React Native will come with a **bundled version** of Hermes.
+React Native comes with a **bundled version** of Hermes.
We will be building a version of Hermes for you whenever we release a new version of React Native. This will make sure you're consuming a version of Hermes which is fully compatible with the version of React Native you're using.
Historically, we had problems with matching versions of Hermes with versions of React Native. This fully eliminates this problem, and offers users a JS engine that is compatible with the specific React Native version.
-This change is fully transparent to users of React Native. You can still enable/disable Hermes using the command described in this page.
+This change is fully transparent to users of React Native. You can still disable Hermes using the command described in this page.
You can [read more about the technical implementation on this page](/architecture/bundled-hermes).
## Confirming Hermes is in use
@@ -95,28 +93,18 @@ Hermes requires [Microsoft Visual C++ 2015 Redistributable](https://www.microsof
### Android
-Edit your `android/app/build.gradle` file and make the change illustrated below:
+Edit your `android/app/gradle.properties` file and make sure `hermesEnabled` is true:
```diff
- project.ext.react = [
- entryFile: "index.js",
-- enableHermes: false // clean and rebuild if changing
-+ enableHermes: true // clean and rebuild if changing
- ]
-
-// ...
-
-if (enableHermes) {
-- def hermesPath = "../../node_modules/hermes-engine/android/";
-- debugImplementation files(hermesPath + "hermes-debug.aar")
-- releaseImplementation files(hermesPath + "hermes-release.aar")
-+ //noinspection GradleDynamicVersion
-+ implementation("com.facebook.react:hermes-engine:+") { // From node_modules
-+ exclude group:'com.facebook.fbjni'
-+ }
-} else {
+# Use this property to enable or disable the Hermes JS engine.
+# If set to false, you will be using JSC instead.
+hermesEnabled=true
```
+:::note
+This property was added in React Native 0.71. If you can't find it in your `gradle.properties` file, please refer to the documentation for the corresponding React Native version you're using.
+:::
+
Also, if you're using ProGuard, you will need to add these rules in `proguard-rules.pro` :
```
@@ -136,10 +124,6 @@ That's it! You should now be able to develop and deploy your app as usual:
$ npx react-native run-android
```
-:::note Note about Android App Bundles
-Android app bundles are supported from React Native 0.62 and up.
-:::
-
### iOS
Since React Native 0.64, Hermes also runs on iOS. To enable Hermes for iOS, edit your `ios/Podfile` file and make the change illustrated below:
@@ -164,8 +148,6 @@ Once you've configured it, you can install the Hermes pods with:
$ cd ios && pod install
```
-
-
That's it! You should now be able to develop and deploy your app as usual:
```shell
@@ -174,7 +156,7 @@ $ npx react-native run-ios
## Switching back to JavaScriptCore
-React Native also supports using JavaScriptCore as the JS engine. Follow these instructions to opt-out of Hermes.
+React Native also supports using JavaScriptCore as the [JavaScript engine](javascript-environment). Follow these instructions to opt-out of Hermes.
### Android
diff --git a/docs/image-style-props.md b/docs/image-style-props.md
index 76fac320948..4dd8a25c58c 100644
--- a/docs/image-style-props.md
+++ b/docs/image-style-props.md
@@ -13,8 +13,8 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import con
```SnackPlayer name=Image%20Resize%20Modes%20Function%20Component%20Example
-import React from "react";
-import { View, Image, Text, StyleSheet } from "react-native";
+import React from 'react';
+import {View, Image, Text, StyleSheet} from 'react-native';
const DisplayAnImageWithStyle = () => {
return (
@@ -22,71 +22,71 @@ const DisplayAnImageWithStyle = () => {
resizeMode : coverresizeMode : containresizeMode : stretchresizeMode : repeatresizeMode : center
);
-}
+};
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "space-around",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
@@ -96,8 +96,8 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Image%20Resize%20Modes%20Class%20Component%20Example
-import React, { Component } from "react";
-import { View, Image, StyleSheet, Text } from "react-native";
+import React, {Component} from 'react';
+import {View, Image, StyleSheet, Text} from 'react-native';
class DisplayAnImageWithStyle extends Component {
render() {
@@ -106,55 +106,55 @@ class DisplayAnImageWithStyle extends Component {
resizeMode : coverresizeMode : containresizeMode : stretchresizeMode : repeatresizeMode : center
@@ -165,13 +165,13 @@ class DisplayAnImageWithStyle extends Component {
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "space-around",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
@@ -186,35 +186,35 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Style%20BorderWidth%20and%20BorderColor%20Function%20Component%20Example
-import React from "react";
-import { View, Image, StyleSheet, Text } from "react-native";
+import React from 'react';
+import {View, Image, StyleSheet, Text} from 'react-native';
const DisplayAnImageWithStyle = () => {
return (
borderColor & borderWidth
);
-}
+};
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "center",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
@@ -224,8 +224,8 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Style%20BorderWidth%20and%20BorderColor%20Class%20Component%20Example
-import React, { Component } from "react";
-import { View, Image, StyleSheet, Text } from "react-native";
+import React, {Component} from 'react';
+import {View, Image, StyleSheet, Text} from 'react-native';
class DisplayAnImageWithStyle extends Component {
render() {
@@ -233,12 +233,12 @@ class DisplayAnImageWithStyle extends Component {
borderColor & borderWidth
@@ -248,13 +248,13 @@ class DisplayAnImageWithStyle extends Component {
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "center",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
@@ -269,8 +269,8 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Style%20Border%20Radius%20Function%20Component%20Example
-import React from "react";
-import { View, Image, StyleSheet, Text } from "react-native";
+import React from 'react';
+import {View, Image, StyleSheet, Text} from 'react-native';
const DisplayAnImageWithStyle = () => {
return (
@@ -280,9 +280,9 @@ const DisplayAnImageWithStyle = () => {
style={{
borderTopRightRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderTopRightRadius
@@ -291,9 +291,9 @@ const DisplayAnImageWithStyle = () => {
style={{
borderBottomRightRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderBottomRightRadius
@@ -302,9 +302,9 @@ const DisplayAnImageWithStyle = () => {
style={{
borderBottomLeftRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderBottomLeftRadius
@@ -313,25 +313,25 @@ const DisplayAnImageWithStyle = () => {
style={{
borderTopLeftRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderTopLeftRadius
);
-}
+};
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "space-around",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
@@ -341,8 +341,8 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Style%20Border%20Radius%20Class%20Component%20Example
-import React, { Component } from "react";
-import { View, Image, StyleSheet, Text } from "react-native";
+import React, {Component} from 'react';
+import {View, Image, StyleSheet, Text} from 'react-native';
class DisplayAnImageWithStyle extends Component {
render() {
@@ -353,9 +353,9 @@ class DisplayAnImageWithStyle extends Component {
style={{
borderTopRightRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderTopRightRadius
@@ -364,9 +364,9 @@ class DisplayAnImageWithStyle extends Component {
style={{
borderBottomRightRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderBottomRightRadius
@@ -375,9 +375,9 @@ class DisplayAnImageWithStyle extends Component {
style={{
borderBottomLeftRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderBottomLeftRadius
@@ -386,9 +386,9 @@ class DisplayAnImageWithStyle extends Component {
style={{
borderTopLeftRadius: 20,
height: 100,
- width: 200
+ width: 200,
}}
- source={require("@expo/snack-static/react-native-logo.png")}
+ source={require('@expo/snack-static/react-native-logo.png')}
/>
borderTopLeftRadius
@@ -399,13 +399,13 @@ class DisplayAnImageWithStyle extends Component {
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "space-around",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'space-around',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
@@ -420,35 +420,35 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Style%20tintColor%20Function%20Component
-import React from "react";
-import { View, Image, StyleSheet, Text } from "react-native";
+import React from 'react';
+import {View, Image, StyleSheet, Text} from 'react-native';
const DisplayAnImageWithStyle = () => {
return (
tintColor
);
-}
+};
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "center",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
@@ -458,8 +458,8 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Style%20tintColor%20Class%20Component
-import React, { Component } from "react";
-import { View, Image, StyleSheet, Text } from "react-native";
+import React, {Component} from 'react';
+import {View, Image, StyleSheet, Text} from 'react-native';
class DisplayAnImageWithStyle extends Component {
render() {
@@ -467,12 +467,12 @@ class DisplayAnImageWithStyle extends Component {
tintColor
@@ -482,13 +482,13 @@ class DisplayAnImageWithStyle extends Component {
const styles = StyleSheet.create({
container: {
- display: "flex",
- flexDirection: "vertical",
- justifyContent: "center",
- alignItems: "center",
- height: "100%",
- textAlign: "center"
- }
+ display: 'flex',
+ flexDirection: 'column',
+ justifyContent: 'center',
+ alignItems: 'center',
+ height: '100%',
+ textAlign: 'center',
+ },
});
export default DisplayAnImageWithStyle;
diff --git a/docs/image.md b/docs/image.md
index ad09cb513e1..3b55e92815a 100644
--- a/docs/image.md
+++ b/docs/image.md
@@ -17,9 +17,8 @@ This example shows fetching and displaying an image from local storage as well a
```SnackPlayer name=Function%20Component%20Example
-
import React from 'react';
-import { View, Image, StyleSheet } from 'react-native';
+import {View, Image, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
container: {
@@ -56,7 +55,7 @@ const DisplayAnImage = () => {
/>
);
-}
+};
export default DisplayAnImage;
```
@@ -65,9 +64,8 @@ export default DisplayAnImage;
```SnackPlayer name=Class%20Component%20Example
-
-import React, { Component } from 'react';
-import { AppRegistry, View, Image, StyleSheet } from 'react-native';
+import React, {Component} from 'react';
+import {View, Image, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
container: {
@@ -97,7 +95,9 @@ class DisplayAnImage extends Component {
/>
);
@@ -116,9 +116,8 @@ You can also add `style` to an image:
```SnackPlayer name=Function%20Component%20Example
-
import React from 'react';
-import { View, Image, StyleSheet } from 'react-native';
+import {View, Image, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
container: {
@@ -140,7 +139,7 @@ const DisplayAnImageWithStyle = () => {
/>
);
-}
+};
export default DisplayAnImageWithStyle;
```
@@ -149,16 +148,15 @@ export default DisplayAnImageWithStyle;
```SnackPlayer name=Class%20Component%20Example
-
-import React, { Component } from 'react';
-import { View, Image, StyleSheet } from 'react-native';
+import React, {Component} from 'react';
+import {View, Image, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
stretch: {
width: 50,
height: 200,
- resizeMode: 'stretch'
- }
+ resizeMode: 'stretch',
+ },
});
class DisplayAnImageWithStyle extends Component {
@@ -237,6 +235,16 @@ The text that's read by the screen reader when the user interacts with the image
---
+### `alt`
+
+A string that defines an alternative text description of the image, which will be read by the screen reader when the user interacts with it. Using this will automatically mark this element as accessible.
+
+| Type |
+| ------ |
+| string |
+
+---
+
### `blurRadius`
blurRadius: the blur radius of the blur filter added to the image.
@@ -314,13 +322,23 @@ Similarly to `source`, this property represents the resource used to render the
---
+### `objectFit`
+
+Determines how to resize the image when the frame doesn't match the raw image dimensions.
+
+| Type | Default |
+| ------------------------------------------------------ | --------- |
+| enum(`'cover'`, `'contain'`, `'fill'`, `'scale-down'`) | `'cover'` |
+
+---
+
### `onError`
Invoked on load error.
-| Type |
-| -------------------------------------- |
-| (`{ nativeEvent: { error } }`) => void |
+| Type |
+| ----------------------------------- |
+| (`{nativeEvent: {error} }`) => void |
---
@@ -328,9 +346,9 @@ Invoked on load error.
Invoked on mount and on layout changes.
-| Type |
-| ----------------------------------------------------- |
-| ({ nativeEvent: [LayoutEvent](layoutevent) }) => void |
+| Type |
+| ------------------------------------------------- |
+| ({nativeEvent: [LayoutEvent]layoutevent)} => void |
---
@@ -340,9 +358,9 @@ Invoked when load completes successfully.
**Example:** `onLoad={({nativeEvent: {source: {width, height}}}) => setImageRealSize({width, height})}`
-| Type |
-| ----------------------------------------------------------------- |
-| ({ nativeEvent: [ImageLoadEvent](image#imageloadevent) }) => void |
+| Type |
+| ------------------------------------------------------------- |
+| ({nativeEvent: [ImageLoadEvent]image#imageloadevent)} => void |
---
@@ -382,9 +400,9 @@ Invoked when a partial load of the image is complete. The definition of what con
Invoked on download progress.
-| Type |
-| ---------------------------------------------- |
-| (`{ nativeEvent: { loaded, total } }`) => void |
+| Type |
+| ------------------------------------------- |
+| (`{nativeEvent: {loaded, total} }`) => void |
---
@@ -531,8 +549,8 @@ Width of the image component.
### `abortPrefetch()`
Android
-```jsx
-Image.abortPrefetch(requestId);
+```tsx
+static abortPrefetch(requestId: number);
```
Abort prefetch request.
@@ -547,8 +565,12 @@ Abort prefetch request.
### `getSize()`
-```jsx
-Image.getSize(uri, success, [failure]);
+```tsx
+static getSize(
+ uri: string,
+ success: (width: number, height: number) => void,
+ failure?: (error: any) => void,
+): any;
```
Retrieve the width and height (in pixels) of an image prior to displaying it. This method can fail if the image cannot be found, or fails to download.
@@ -567,8 +589,13 @@ In order to retrieve the image dimensions, the image may first need to be loaded
### `getSizeWithHeaders()`
-```jsx
-Image.getSizeWithHeaders(uri, headers, success, [failure]);
+```tsx
+static getSizeWithHeaders(
+ uri: string,
+ headers: {[index: string]: string},
+ success: (width: number, height: number) => void,
+ failure?: (error: any) => void,
+): any;
```
Retrieve the width and height (in pixels) of an image prior to displaying it with the ability to provide the headers for the request. This method can fail if the image cannot be found, or fails to download. It also does not work for static image resources.
@@ -588,7 +615,7 @@ In order to retrieve the image dimensions, the image may first need to be loaded
### `prefetch()`
-```jsx
+```tsx
await Image.prefetch(url);
```
@@ -605,8 +632,10 @@ Prefetches a remote image for later use by downloading it to the disk cache. Ret
### `queryCache()`
-```jsx
-await Image.queryCache(urls);
+```tsx
+static queryCache(
+ urls: string[],
+): Promise>;
```
Perform cache interrogation. Returns a promise which resolves to a mapping from URL to cache status, such as "disk", "memory" or "disk/memory". If a requested URL is not in the mapping, it means it's not in the cache.
@@ -621,11 +650,16 @@ Perform cache interrogation. Returns a promise which resolves to a mapping from
### `resolveAssetSource()`
-```jsx
-Image.resolveAssetSource(source);
+```tsx
+static resolveAssetSource(source: ImageSourcePropType): {
+ height: number;
+ width: number;
+ scale: number;
+ uri: string;
+};
```
-Resolves an asset reference into an object which has the properties `uri`, `width`, and `height`.
+Resolves an asset reference into an object which has the properties `uri`, `scale`, `width`, and `height`.
**Parameters:**
diff --git a/docs/imagebackground.md b/docs/imagebackground.md
index be2f8f0f0c8..517f3bc2dbc 100644
--- a/docs/imagebackground.md
+++ b/docs/imagebackground.md
@@ -12,10 +12,10 @@ Note that you must specify some width and height style attributes.
## Example
```SnackPlayer name=ImageBackground
-import React from "react";
-import { ImageBackground, StyleSheet, Text, View } from "react-native";
+import React from 'react';
+import {ImageBackground, StyleSheet, Text, View} from 'react-native';
-const image = { uri: "https://reactjs.org/logo-og.png" };
+const image = {uri: 'https://reactjs.org/logo-og.png'};
const App = () => (
@@ -31,16 +31,16 @@ const styles = StyleSheet.create({
},
image: {
flex: 1,
- justifyContent: "center"
+ justifyContent: 'center',
},
text: {
- color: "white",
+ color: 'white',
fontSize: 42,
lineHeight: 84,
- fontWeight: "bold",
- textAlign: "center",
- backgroundColor: "#000000c0"
- }
+ fontWeight: 'bold',
+ textAlign: 'center',
+ backgroundColor: '#000000c0',
+ },
});
export default App;
diff --git a/docs/imagepickerios.md b/docs/imagepickerios.md
index f83c31d8c0c..1fd3f7c96f3 100644
--- a/docs/imagepickerios.md
+++ b/docs/imagepickerios.md
@@ -3,7 +3,7 @@ id: imagepickerios
title: 'đ§ ImagePickerIOS'
---
-> **Deprecated.** Use one of the [community packages](https://reactnative.directory/?search=image+picker) instead.
+> **Removed.** Use one of the [community packages](https://reactnative.directory/?search=image+picker) instead.
---
diff --git a/docs/images.md b/docs/images.md
index 5dc1a1af733..8b900aacd08 100644
--- a/docs/images.md
+++ b/docs/images.md
@@ -7,7 +7,7 @@ title: Images
React Native provides a unified way of managing images and other media assets in your Android and iOS apps. To add a static image to your app, place it somewhere in your source code tree and reference it like this:
-```jsx
+```tsx
```
@@ -26,7 +26,7 @@ You can use the `@2x` and `@3x` suffixes to provide images for different screen
...and `button.js` code contains:
-```jsx
+```tsx
```
@@ -46,7 +46,7 @@ Here are some benefits that you get:
In order for this to work, the image name in `require` has to be known statically.
-```jsx
+```tsx
// GOOD
;
@@ -63,7 +63,7 @@ var icon = this.props.active
;
```
-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.
+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
@@ -79,19 +79,19 @@ If you are building a hybrid app (some UIs in React Native, some UIs in platform
For images included via Xcode asset catalogs or in the Android drawable folder, use the image name without the extension:
-```jsx
+```tsx
```
For images in the Android assets folder, use the `asset:/` scheme:
-```jsx
+```tsx
```
@@ -101,7 +101,7 @@ These approaches provide no safety checks. It's up to you to guarantee that thos
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](publishing-to-app-store.md#1-enable-app-transport-security) requirements on iOS.
-```jsx
+```tsx
// GOOD
@@ -114,17 +114,17 @@ Many of the images you will display in your app will not be available at compile
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
+```tsx
```
@@ -136,16 +136,16 @@ Sometimes, you might be getting encoded image data from a REST API call. You can
This is recommended for very small and dynamic images only, like icons in a list from a DB.
:::
-```jsx
+```tsx
// include at least width and height!
```
@@ -159,13 +159,13 @@ In some cases you might only want to display an image if it is already in the lo
- `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
+```tsx
```
@@ -185,7 +185,7 @@ _In React Native_ this behavior is intentionally not implemented. It is more wor
For example, the result of `require('./my-icon.png')` might be:
-```jsx
+```tsx
{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}
```
@@ -193,8 +193,8 @@ For example, the result of `require('./my-icon.png')` might be:
In React Native, one interesting decision is that the `src` attribute is named `source` and doesn't take a string but an object with a `uri` attribute.
-```jsx
-
+```tsx
+
```
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.
@@ -207,7 +207,7 @@ A common feature request from developers familiar with the web is `background-im
You might not want to use `` in some cases, since the implementation is basic. Refer to ``'s [documentation](imagebackground.md) for more insight, and create your own custom component when needed.
-```jsx
+```tsx
return (
Inside
diff --git a/docs/improvingux.md b/docs/improvingux.md
index a461d08a11e..e36cd05ef68 100644
--- a/docs/improvingux.md
+++ b/docs/improvingux.md
@@ -3,6 +3,8 @@ id: improvingux
title: Improving User Experience
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
## Configure text inputs
Entering text on touch phone is a challenge - small screen, software keyboard. But based on what kind of data you need, you can make it easier by properly configuring the text inputs:
@@ -15,10 +17,19 @@ Entering text on touch phone is a challenge - small screen, software keyboard. B
Check out [`TextInput` docs](textinput.md) for more configuration options.
-```SnackPlayer name=TextInput%20form%20example
-import React, { useState, useRef } from 'react';
-import { Text, StatusBar, TextInput, View, StyleSheet } from 'react-native';
-import { Constants } from 'expo';
+
+
+
+```SnackPlayer name=TextInput%20form%20example&ext=js
+import React, {useState, useRef} from 'react';
+import {
+ Alert,
+ Text,
+ StatusBar,
+ TextInput,
+ View,
+ StyleSheet,
+} from 'react-native';
const App = () => {
const emailInput = useRef(null);
@@ -26,7 +37,9 @@ const App = () => {
const [email, setEmail] = useState('');
const submit = () => {
- alert(`Welcome, ${name}! Confirmation email has been sent to ${email}`);
+ Alert.alert(
+ `Welcome, ${name}! Confirmation email has been sent to ${email}`,
+ );
};
return (
@@ -43,7 +56,7 @@ const App = () => {
setName(name)}
+ onChangeText={text => setName(text)}
placeholder="Full Name"
autoFocus={true}
autoCapitalize="words"
@@ -56,7 +69,101 @@ const App = () => {
setEmail(email)}
+ onChangeText={text => setEmail(text)}
+ ref={emailInput}
+ placeholder="email@example.com"
+ autoCapitalize="none"
+ autoCorrect={false}
+ keyboardType="email-address"
+ returnKeyType="send"
+ onSubmitEditing={submit}
+ blurOnSubmit={true}
+ />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ header: {
+ paddingTop: 64,
+ padding: 20,
+ backgroundColor: '#282c34',
+ },
+ description: {
+ fontSize: 14,
+ color: 'white',
+ },
+ input: {
+ margin: 20,
+ marginBottom: 0,
+ height: 34,
+ paddingHorizontal: 10,
+ borderRadius: 4,
+ borderColor: '#ccc',
+ borderWidth: 1,
+ fontSize: 16,
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=TextInput%20form%20example&ext=tsx
+import React, {useState, useRef} from 'react';
+import {
+ Alert,
+ Text,
+ StatusBar,
+ TextInput,
+ View,
+ StyleSheet,
+} from 'react-native';
+
+const App = () => {
+ const emailInput = useRef(null);
+ const [name, setName] = useState('');
+ const [email, setEmail] = useState('');
+
+ const submit = () => {
+ Alert.alert(
+ `Welcome, ${name}! Confirmation email has been sent to ${email}`,
+ );
+ };
+
+ return (
+
+
+
+
+ This demo shows how using available TextInput customizations can make
+ forms much easier to use. Try completing the form and notice that
+ different fields have specific optimizations and the return key
+ changes from focusing next input to submitting the form.
+
+
+ setName(text)}
+ placeholder="Full Name"
+ autoFocus={true}
+ autoCapitalize="words"
+ autoCorrect={true}
+ keyboardType="default"
+ returnKeyType="next"
+ onSubmitEditing={() => emailInput.current?.focus()}
+ blurOnSubmit={false}
+ />
+ setEmail(text)}
ref={emailInput}
placeholder="email@example.com"
autoCapitalize="none"
@@ -98,13 +205,20 @@ const styles = StyleSheet.create({
export default App;
```
+
+
+
## Manage layout when keyboard is visible
Software keyboard takes almost half of the screen. If you have interactive elements that can get covered by the keyboard, make sure they are still accessible by using the [`KeyboardAvoidingView` component](keyboardavoidingview.md).
-```SnackPlayer name=KeyboardAvoidingView%20example
-import React, { useState, useRef } from 'react';
+
+
+
+```SnackPlayer name=KeyboardAvoidingView%20example&ext=js
+import React, {useState, useRef} from 'react';
import {
+ Alert,
Text,
Button,
StatusBar,
@@ -120,7 +234,7 @@ const App = () => {
const submit = () => {
emailInput.current.blur();
- alert(`Confirmation email has been sent to ${email}`);
+ Alert.alert(`Confirmation email has been sent to ${email}`);
};
return (
@@ -138,7 +252,7 @@ const App = () => {
setEmail(email)}
+ onChangeText={text => setEmail(text)}
ref={emailInput}
placeholder="email@example.com"
autoCapitalize="none"
@@ -195,12 +309,112 @@ const styles = StyleSheet.create({
export default App;
```
+
+
+
+```SnackPlayer name=KeyboardAvoidingView%20example&ext=tsx
+import React, {useState, useRef} from 'react';
+import {
+ Alert,
+ Text,
+ Button,
+ StatusBar,
+ TextInput,
+ KeyboardAvoidingView,
+ View,
+ StyleSheet,
+} from 'react-native';
+
+const App = () => {
+ const emailInput = useRef(null);
+ const [email, setEmail] = useState('');
+
+ const submit = () => {
+ emailInput.current?.blur();
+ Alert.alert(`Confirmation email has been sent to ${email}`);
+ };
+
+ return (
+
+
+
+
+ This demo shows how to avoid covering important UI elements with the
+ software keyboard. Focus the email input below and notice that the
+ Sign Up button and the text adjusted positions to make sure they are
+ not hidden under the keyboard.
+
+
+
+ setEmail(text)}
+ ref={emailInput}
+ placeholder="email@example.com"
+ autoCapitalize="none"
+ autoCorrect={false}
+ keyboardType="email-address"
+ returnKeyType="send"
+ onSubmitEditing={submit}
+ blurOnSubmit={true}
+ />
+
+
+ Some important legal fine print here
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ header: {
+ paddingTop: 64,
+ padding: 20,
+ backgroundColor: '#282c34',
+ },
+ description: {
+ fontSize: 14,
+ color: 'white',
+ },
+ input: {
+ margin: 20,
+ marginBottom: 0,
+ height: 34,
+ paddingHorizontal: 10,
+ borderRadius: 4,
+ borderColor: '#ccc',
+ borderWidth: 1,
+ fontSize: 16,
+ },
+ legal: {
+ margin: 10,
+ color: '#333',
+ fontSize: 12,
+ textAlign: 'center',
+ },
+ form: {
+ flex: 1,
+ justifyContent: 'space-between',
+ },
+});
+
+export default App;
+```
+
+
+
+
## Make tappable areas larger
On mobile phones it's hard to be very precise when pressing buttons. Make sure all interactive elements are 44x44 or larger. One way to do this is to leave enough space for the element, `padding`, `minWidth` and `minHeight` style values can be useful for that. Alternatively, you can use [`hitSlop` prop](touchablewithoutfeedback.md#hitslop) to increase interactive area without affecting the layout. Here's a demo:
```SnackPlayer name=HitSlop%20example
-import React, { Component } from 'react';
+import React from 'react';
import {
Text,
StatusBar,
@@ -228,7 +442,7 @@ const App = () => {
+ hitSlop={{top: 20, left: 20, bottom: 20, right: 20}}>
With hitSlop
@@ -294,7 +508,7 @@ const SUPPORTS_NATIVE_FEEDBACK =
Platform.OS === 'android' && Platform.Version >= 21;
const noop = () => {};
-const defaultHitSlop = { top: 15, bottom: 15, right: 15, left: 15 };
+const defaultHitSlop = {top: 15, bottom: 15, right: 15, left: 15};
const ButtonsWithNativeFeedback = () => (
diff --git a/docs/inputaccessoryview.md b/docs/inputaccessoryview.md
index 4de484ad34c..a2300c729f3 100644
--- a/docs/inputaccessoryview.md
+++ b/docs/inputaccessoryview.md
@@ -8,10 +8,10 @@ A component which enables customization of the keyboard input accessory view on
To use this component wrap your custom toolbar with the InputAccessoryView component, and set a `nativeID`. Then, pass that `nativeID` as the `inputAccessoryViewID` of whatever `TextInput` you desire. A basic example:
```SnackPlayer name=InputAccessoryView&supportedPlatforms=ios
-import React, { useState } from 'react';
-import { Button, InputAccessoryView, ScrollView, TextInput } from 'react-native';
+import React, {useState} from 'react';
+import {Button, InputAccessoryView, ScrollView, TextInput} from 'react-native';
-export default App = () => {
+const App = () => {
const inputAccessoryViewID = 'uniqueID';
const initialText = '';
const [text, setText] = useState(initialText);
@@ -31,14 +31,13 @@ export default App = () => {
/>
- setText(initialText)}
- title="Clear text"
- />
+ setText(initialText)} title="Clear text" />
>
);
-}
+};
+
+export default App;
```
This component can also be used to create sticky text inputs (text inputs which are anchored to the top of the keyboard). To do this, wrap a `TextInput` with the `InputAccessoryView` component, and don't set a `nativeID`. For an example, look at [InputAccessoryViewExample.js](https://github.com/facebook/react-native/blob/master/packages/rn-tester/js/examples/InputAccessoryView/InputAccessoryViewExample.js).
diff --git a/docs/interactionmanager.md b/docs/interactionmanager.md
index 41588b6fb02..cab9bd01144 100644
--- a/docs/interactionmanager.md
+++ b/docs/interactionmanager.md
@@ -3,11 +3,13 @@ id: interactionmanager
title: InteractionManager
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
InteractionManager allows long-running work to be scheduled after any interactions/animations have completed. In particular, this allows JavaScript animations to run smoothly.
Applications can schedule tasks to run after interactions with the following:
-```jsx
+```tsx
InteractionManager.runAfterInteractions(() => {
// ...long-running synchronous task...
});
@@ -23,7 +25,7 @@ The touch handling system considers one or more active touches to be an 'interac
InteractionManager also allows applications to register animations by creating an interaction 'handle' on animation start, and clearing it upon completion:
-```jsx
+```tsx
var handle = InteractionManager.createInteractionHandle();
// run animation... (`runAfterInteractions` tasks are queued)
// later, on animation completion:
@@ -41,8 +43,11 @@ By default, queued tasks are executed together in a loop in one `setImmediate` b
### Basic
-```SnackPlayer name=InteractionManager%20Function%20Component%20Basic%20Example&supportedPlatforms=ios,android
-import React, { useState, useEffect } from "react";
+
+
+
+```SnackPlayer name=InteractionManager%20Function%20Component%20Basic%20Example&supportedPlatforms=ios,android&ext=js
+import React, {useState, useEffect} from 'react';
import {
Alert,
Animated,
@@ -51,60 +56,148 @@ import {
StyleSheet,
Text,
View,
-} from "react-native";
+} from 'react-native';
const instructions = Platform.select({
- ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
+ ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
- "Double tap R on your keyboard to reload,\n" +
- "Shake or press menu button for dev menu",
+ 'Double tap R on your keyboard to reload,\n' +
+ 'Shake or press menu button for dev menu',
+});
+
+const useFadeIn = (duration = 5000) => {
+ const [opacity] = useState(new Animated.Value(0));
+
+ // Running the animation when the component is mounted
+ useEffect(() => {
+ // Animated.timing() create a interaction handle by default, if you want to disabled that
+ // behaviour you can set isInteraction to false to disabled that.
+ Animated.timing(opacity, {
+ toValue: 1,
+ duration,
+ useNativeDriver: true,
+ }).start();
+ }, [duration, opacity]);
+
+ return opacity;
+};
+
+const Ball = ({onShown}) => {
+ const opacity = useFadeIn();
+
+ // Running a method after the animation
+ useEffect(() => {
+ const interactionPromise = InteractionManager.runAfterInteractions(() =>
+ onShown(),
+ );
+ return () => interactionPromise.cancel();
+ }, [onShown]);
+
+ return ;
+};
+
+const App = () => {
+ return (
+
+ {instructions}
+ Alert.alert('Animation is done')} />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ ball: {
+ width: 100,
+ height: 100,
+ backgroundColor: 'salmon',
+ borderRadius: 100,
+ },
});
-const useMount = func => useEffect(() => func(), []);
+export default App;
+```
+
+
+
+
+```SnackPlayer name=InteractionManager%20Function%20Component%20Basic%20Example&supportedPlatforms=ios,android&ext=tsx
+import React, {useState, useEffect} from 'react';
+import {
+ Alert,
+ Animated,
+ InteractionManager,
+ Platform,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+
+const instructions = Platform.select({
+ ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
+ android:
+ 'Double tap R on your keyboard to reload,\n' +
+ 'Shake or press menu button for dev menu',
+});
const useFadeIn = (duration = 5000) => {
const [opacity] = useState(new Animated.Value(0));
// Running the animation when the component is mounted
- useMount(() => {
+ useEffect(() => {
// Animated.timing() create a interaction handle by default, if you want to disabled that
// behaviour you can set isInteraction to false to disabled that.
Animated.timing(opacity, {
toValue: 1,
duration,
+ useNativeDriver: true,
}).start();
- });
+ }, [duration, opacity]);
return opacity;
};
-const Ball = ({ onShown }) => {
+type BallProps = {
+ onShown: () => void;
+};
+
+const Ball = ({onShown}: BallProps) => {
const opacity = useFadeIn();
// Running a method after the animation
- useMount(() => {
- const interactionPromise = InteractionManager.runAfterInteractions(() => onShown());
+ useEffect(() => {
+ const interactionPromise = InteractionManager.runAfterInteractions(() =>
+ onShown(),
+ );
return () => interactionPromise.cancel();
- });
+ }, [onShown]);
- return ;
+ return ;
};
const App = () => {
return (
{instructions}
- Alert.alert("Animation is done")} />
+ Alert.alert('Animation is done')} />
);
};
const styles = StyleSheet.create({
- container: { flex: 1, justifyContent: "center", alignItems: "center" },
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
ball: {
width: 100,
height: 100,
- backgroundColor: "salmon",
+ backgroundColor: 'salmon',
borderRadius: 100,
},
});
@@ -112,10 +205,16 @@ const styles = StyleSheet.create({
export default App;
```
+
+
+
### Advanced
-```SnackPlayer name=InteractionManager%20Function%20Component%20Advanced%20Example&supportedPlatforms=ios,android
-import React, { useEffect } from "react";
+
+
+
+```SnackPlayer name=InteractionManager%20Function%20Component%20Advanced%20Example&supportedPlatforms=ios,android&ext=js
+import React, {useEffect} from 'react';
import {
Alert,
Animated,
@@ -124,39 +223,115 @@ import {
StyleSheet,
Text,
View,
-} from "react-native";
+} from 'react-native';
const instructions = Platform.select({
- ios: "Press Cmd+R to reload,\n" + "Cmd+D or shake for dev menu",
+ ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
android:
- "Double tap R on your keyboard to reload,\n" +
- "Shake or press menu button for dev menu",
+ 'Double tap R on your keyboard to reload,\n' +
+ 'Shake or press menu button for dev menu',
+});
+
+// You can create a custom interaction/animation and add
+// support for InteractionManager
+const useCustomInteraction = (timeLocked = 2000) => {
+ useEffect(() => {
+ const handle = InteractionManager.createInteractionHandle();
+
+ setTimeout(
+ () => InteractionManager.clearInteractionHandle(handle),
+ timeLocked,
+ );
+
+ return () => InteractionManager.clearInteractionHandle(handle);
+ }, [timeLocked]);
+};
+
+const Ball = ({onInteractionIsDone}) => {
+ useCustomInteraction();
+
+ // Running a method after the interaction
+ useEffect(() => {
+ InteractionManager.runAfterInteractions(() => onInteractionIsDone());
+ }, [onInteractionIsDone]);
+
+ return ;
+};
+
+const App = () => {
+ return (
+
+ {instructions}
+ Alert.alert('Interaction is done')} />
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ ball: {
+ width: 100,
+ height: 100,
+ backgroundColor: 'salmon',
+ borderRadius: 100,
+ },
});
-const useMount = func => useEffect(() => func(), []);
+export default App;
+```
+
+
+
+
+```SnackPlayer name=InteractionManager%20Function%20Component%20Advanced%20Example&supportedPlatforms=ios,android&ext=tsx
+import React, {useEffect} from 'react';
+import {
+ Alert,
+ Animated,
+ InteractionManager,
+ Platform,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+
+const instructions = Platform.select({
+ ios: 'Press Cmd+R to reload,\n' + 'Cmd+D or shake for dev menu',
+ android:
+ 'Double tap R on your keyboard to reload,\n' +
+ 'Shake or press menu button for dev menu',
+});
// You can create a custom interaction/animation and add
// support for InteractionManager
const useCustomInteraction = (timeLocked = 2000) => {
- useMount(() => {
+ useEffect(() => {
const handle = InteractionManager.createInteractionHandle();
setTimeout(
() => InteractionManager.clearInteractionHandle(handle),
- timeLocked
+ timeLocked,
);
return () => InteractionManager.clearInteractionHandle(handle);
- });
+ }, [timeLocked]);
};
-const Ball = ({ onInteractionIsDone }) => {
+type BallProps = {
+ onInteractionIsDone: () => void;
+};
+
+const Ball = ({onInteractionIsDone}: BallProps) => {
useCustomInteraction();
// Running a method after the interaction
- useMount(() => {
+ useEffect(() => {
InteractionManager.runAfterInteractions(() => onInteractionIsDone());
- });
+ }, [onInteractionIsDone]);
return ;
};
@@ -165,17 +340,21 @@ const App = () => {
return (
{instructions}
- Alert.alert("Interaction is done")} />
+ Alert.alert('Interaction is done')} />
);
};
const styles = StyleSheet.create({
- container: { flex: 1, justifyContent: "center", alignItems: "center" },
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
ball: {
width: 100,
height: 100,
- backgroundColor: "salmon",
+ backgroundColor: 'salmon',
borderRadius: 100,
},
});
@@ -183,6 +362,9 @@ const styles = StyleSheet.create({
export default App;
```
+
+
+
> **Note**: `InteractionManager.runAfterInteractions()` is not working properly on web. It triggers immediately without waiting until the interaction is finished.
# Reference
@@ -191,8 +373,8 @@ export default App;
### `runAfterInteractions()`
-```jsx
-static runAfterInteractions(task)
+```tsx
+static runAfterInteractions(task?: (() => any) | SimpleTask | PromiseTask);
```
Schedule a function to run after all interactions have completed. Returns a cancellable "promise".
@@ -201,8 +383,8 @@ Schedule a function to run after all interactions have completed. Returns a canc
### `createInteractionHandle()`
-```jsx
-static createInteractionHandle()
+```tsx
+static createInteractionHandle(): Handle;
```
Notify manager that an interaction has started.
@@ -211,8 +393,8 @@ Notify manager that an interaction has started.
### `clearInteractionHandle()`
-```jsx
-static clearInteractionHandle(handle)
+```tsx
+static clearInteractionHandle(handle: Handle);
```
Notify manager that an interaction has completed.
@@ -221,8 +403,8 @@ Notify manager that an interaction has completed.
### `setDeadline()`
-```jsx
-static setDeadline(deadline)
+```tsx
+static setDeadline(deadline: number);
```
A positive number will use setTimeout to schedule any tasks after the eventLoopRunningTime hits the deadline value, otherwise all tasks will be executed in one setImmediate batch (default).
diff --git a/docs/intro-react-native-components.md b/docs/intro-react-native-components.md
index 54eb7f69311..62bdcc4ec55 100644
--- a/docs/intro-react-native-components.md
+++ b/docs/intro-react-native-components.md
@@ -41,7 +41,7 @@ In the next section, you will start combining these Core Components to learn abo
```SnackPlayer name=Hello%20World
import React from 'react';
-import { View, Text, Image, ScrollView, TextInput } from 'react-native';
+import {View, Text, Image, ScrollView, TextInput} from 'react-native';
const App = () => {
return (
@@ -53,20 +53,20 @@ const App = () => {
source={{
uri: 'https://reactnative.dev/docs/assets/p_cat2.png',
}}
- style={{ width: 200, height: 200 }}
+ style={{width: 200, height: 200}}
/>
);
-}
+};
export default App;
```
diff --git a/docs/intro-react.md b/docs/intro-react.md
index 54b422e1829..b48fca7f140 100644
--- a/docs/intro-react.md
+++ b/docs/intro-react.md
@@ -26,27 +26,25 @@ The rest of this introduction to React uses cats in its examples: friendly, appr
```SnackPlayer name=Your%20Cat
import React from 'react';
-import { Text } from 'react-native';
+import {Text} from 'react-native';
const Cat = () => {
- return (
- Hello, I am your cat!
- );
-}
+ return Hello, I am your cat!;
+};
export default Cat;
```
Here is how you do it: To define your `Cat` component, first use JavaScriptâs [`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import) to import React and React Nativeâs [`Text`](/docs/next/text) Core Component:
-```jsx
+```tsx
import React from 'react';
-import { Text } from 'react-native';
+import {Text} from 'react-native';
```
Your component starts as a function:
-```jsx
+```tsx
const Cat = () => {};
```
@@ -54,7 +52,7 @@ You can think of components as blueprints. Whatever a function component returns
Here the `Cat` component will render a `` element:
-```jsx
+```tsx
const Cat = () => {
return Hello, I am your cat!;
};
@@ -62,7 +60,7 @@ const Cat = () => {
You can export your function component with JavaScriptâs [`export default`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export) for use throughout your app like so:
-```jsx
+```tsx
const Cat = () => {
return Hello, I am your cat!;
};
@@ -76,14 +74,12 @@ export default Cat;
Class components tend to be a bit more verbose than function components.
```SnackPlayer name=Your%20Cat
-import React, { Component } from 'react';
-import { Text } from 'react-native';
+import React, {Component} from 'react';
+import {Text} from 'react-native';
class Cat extends Component {
render() {
- return (
- Hello, I am your cat!
- );
+ return Hello, I am your cat!;
}
}
@@ -92,19 +88,19 @@ export default Cat;
You additionally import `Component` from React:
-```jsx
-import React, { Component } from 'react';
+```tsx
+import React, {Component} from 'react';
```
Your component starts as a class extending `Component` instead of as a function:
-```jsx
+```tsx
class Cat extends Component {}
```
Class components have a `render()` function. Whatever is returned inside it is rendered as a React element:
-```jsx
+```tsx
class Cat extends Component {
render() {
return Hello, I am your cat!;
@@ -114,7 +110,7 @@ class Cat extends Component {
And as with function components, you can export your class component:
-```jsx
+```tsx
class Cat extends Component {
render() {
return Hello, I am your cat!;
@@ -137,39 +133,61 @@ React and React Native use **JSX,** a syntax that lets you write elements inside
```SnackPlayer name=Curly%20Braces
import React from 'react';
-import { Text } from 'react-native';
+import {Text} from 'react-native';
const Cat = () => {
- const name = "Maru";
- return (
- Hello, I am {name}!
- );
-}
+ const name = 'Maru';
+ return Hello, I am {name}!;
+};
export default Cat;
```
Any JavaScript expression will work between curly braces, including function calls like `{getFullName("Rum", "Tum", "Tugger")}`:
-```SnackPlayer name=Curly%20Braces
+
+
+
+```SnackPlayer name=Curly%20Braces&ext=js
import React from 'react';
-import { Text } from 'react-native';
+import {Text} from 'react-native';
const getFullName = (firstName, secondName, thirdName) => {
- return firstName + " " + secondName + " " + thirdName;
-}
+ return firstName + ' ' + secondName + ' ' + thirdName;
+};
const Cat = () => {
- return (
-
- Hello, I am {getFullName("Rum", "Tum", "Tugger")}!
-
- );
-}
+ return Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!;
+};
export default Cat;
```
+
+
+
+```SnackPlayer name=Curly%20Braces&ext=tsx
+import React from 'react';
+import {Text} from 'react-native';
+
+const getFullName = (
+ firstName: string,
+ secondName: string,
+ thirdName: string,
+) => {
+ return firstName + ' ' + secondName + ' ' + thirdName;
+};
+
+const Cat = () => {
+ return Hello, I am {getFullName('Rum', 'Tum', 'Tugger')}!;
+};
+
+export default Cat;
+```
+
+
+
+
You can think of curly braces as creating a portal into JS functionality in your JSX!
> Because JSX is included in the React library, it wonât work if you donât have `import React from 'react'` at the top of your file!
@@ -182,7 +200,7 @@ For example, you can nest [`Text`](text) and [`TextInput`](textinput) inside a [
```SnackPlayer name=Custom%20Components
import React from 'react';
-import { Text, TextInput, View } from 'react-native';
+import {Text, TextInput, View} from 'react-native';
const Cat = () => {
return (
@@ -192,13 +210,13 @@ const Cat = () => {
style={{
height: 40,
borderColor: 'gray',
- borderWidth: 1
+ borderWidth: 1,
}}
defaultValue="Name me!"
/>
);
-}
+};
export default Cat;
```
@@ -223,7 +241,7 @@ You can render this component multiple times and in multiple places without repe
```SnackPlayer name=Multiple%20Components
import React from 'react';
-import { Text, View } from 'react-native';
+import {Text, View} from 'react-native';
const Cat = () => {
return (
@@ -231,7 +249,7 @@ const Cat = () => {
I am also a cat!
);
-}
+};
const Cafe = () => {
return (
@@ -242,7 +260,7 @@ const Cafe = () => {
);
-}
+};
export default Cafe;
```
@@ -255,17 +273,20 @@ You can put as many cats in your cafe as you like. Each `` renders a unique
**Props** is short for âpropertiesâ. Props let you customize React components. For example, here you pass each `` a different `name` for `Cat` to render:
-```SnackPlayer name=Multiple%20Props
+
+
+
+```SnackPlayer name=Multiple%20Props&ext=js
import React from 'react';
-import { Text, View } from 'react-native';
+import {Text, View} from 'react-native';
-const Cat = (props) => {
+const Cat = props => {
return (
Hello, I am {props.name}!
);
-}
+};
const Cafe = () => {
return (
@@ -275,28 +296,65 @@ const Cafe = () => {
);
-}
+};
+
+export default Cafe;
+```
+
+
+
+
+```SnackPlayer name=Multiple%20Props&ext=tsx
+import React from 'react';
+import {Text, View} from 'react-native';
+
+type CatProps = {
+ name: string;
+};
+
+const Cat = (props: CatProps) => {
+ return (
+
+ Hello, I am {props.name}!
+
+ );
+};
+
+const Cafe = () => {
+ return (
+
+
+
+
+
+ );
+};
export default Cafe;
```
+
+
+
Most of React Nativeâs Core Components can be customized with props, too. For example, when using [`Image`](image), you pass it a prop named [`source`](image#source) to define what image it shows:
```SnackPlayer name=Props
import React from 'react';
-import { Text, View, Image } from 'react-native';
+import {Text, View, Image} from 'react-native';
const CatApp = () => {
return (
Hello, I am your cat!
);
-}
+};
export default CatApp;
```
@@ -320,28 +378,31 @@ The following example takes place in a cat cafe where two hungry cats are waitin
You can add state to a component by calling [Reactâs `useState` Hook](https://reactjs.org/docs/hooks-state.html). A Hook is a kind of function that lets you âhook intoâ React features. For example, `useState` is a Hook that lets you add state to function components. You can learn more about [other kinds of Hooks in the React documentation.](https://reactjs.org/docs/hooks-intro.html)
-```SnackPlayer name=State
-import React, { useState } from "react";
-import { Button, Text, View } from "react-native";
+
+
+
+```SnackPlayer name=State&ext=js
+import React, {useState} from 'react';
+import {Button, Text, View} from 'react-native';
-const Cat = (props) => {
+const Cat = props => {
const [isHungry, setIsHungry] = useState(true);
return (
- I am {props.name}, and I am {isHungry ? "hungry" : "full"}!
+ I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
{
setIsHungry(false);
}}
disabled={!isHungry}
- title={isHungry ? "Pour me some milk, please!" : "Thank you!"}
+ title={isHungry ? 'Pour me some milk, please!' : 'Thank you!'}
/>
);
-}
+};
const Cafe = () => {
return (
@@ -350,21 +411,66 @@ const Cafe = () => {
>
);
-}
+};
export default Cafe;
```
+
+
+
+```SnackPlayer name=State&ext=tsx
+import React, {useState} from 'react';
+import {Button, Text, View} from 'react-native';
+
+type CatProps = {
+ name: string;
+};
+
+const Cat = (props: CatProps) => {
+ const [isHungry, setIsHungry] = useState(true);
+
+ return (
+
+
+ I am {props.name}, and I am {isHungry ? 'hungry' : 'full'}!
+
+ {
+ setIsHungry(false);
+ }}
+ disabled={!isHungry}
+ title={isHungry ? 'Pour me some milk, please!' : 'Thank you!'}
+ />
+
+ );
+};
+
+const Cafe = () => {
+ return (
+ <>
+
+
+ >
+ );
+};
+
+export default Cafe;
+```
+
+
+
+
First, you will want to import `useState` from React like so:
-```jsx
-import React, { useState } from 'react';
+```tsx
+import React, {useState} from 'react';
```
Then you declare the componentâs state by calling `useState` inside its function. In this example, `useState` creates an `isHungry` state variable:
-```jsx
-const Cat = (props) => {
+```tsx
+const Cat = (props: CatProps) => {
const [isHungry, setIsHungry] = useState(true);
// ...
};
@@ -381,7 +487,7 @@ It doesnât matter what names you use. But it can be handy to think of the patt
Next you add the [`Button`](button) Core Component and give it an `onPress` prop:
-```jsx
+```tsx
{
setIsHungry(false);
@@ -392,7 +498,7 @@ Next you add the [`Button`](button) Core Component and give it an `onPress` prop
Now, when someone presses the button, `onPress` will fire, calling the `setIsHungry(false)`. This sets the state variable `isHungry` to `false`. When `isHungry` is false, the `Button`âs `disabled` prop is set to `true` and its `title` also changes:
-```jsx
+```tsx
{
return (
<>
@@ -420,27 +526,30 @@ const Cafe = () => {
The older class components approach is a little different when it comes to state.
-```SnackPlayer name=State%20and%20Class%20Components
-import React, { Component } from "react";
-import { Button, Text, View } from "react-native";
+
+
+
+```SnackPlayer name=State%20and%20Class%20Components&ext=js
+import React, {Component} from 'react';
+import {Button, Text, View} from 'react-native';
class Cat extends Component {
- state = { isHungry: true };
+ state = {isHungry: true};
render() {
return (
I am {this.props.name}, and I am
- {this.state.isHungry ? " hungry" : " full"}!
+ {this.state.isHungry ? ' hungry' : ' full'}!
{
- this.setState({ isHungry: false });
+ this.setState({isHungry: false});
}}
disabled={!this.state.isHungry}
title={
- this.state.isHungry ? "Pour me some milk, please!" : "Thank you!"
+ this.state.isHungry ? 'Pour me some milk, please!' : 'Thank you!'
}
/>
@@ -462,24 +571,76 @@ class Cafe extends Component {
export default Cafe;
```
+
+
+
+```SnackPlayer name=State%20and%20Class%20Components&ext=tsx
+import React, {Component} from 'react';
+import {Button, Text, View} from 'react-native';
+
+type CatProps = {
+ name: string;
+};
+
+class Cat extends Component {
+ state = {isHungry: true};
+
+ render() {
+ return (
+
+
+ I am {this.props.name}, and I am
+ {this.state.isHungry ? ' hungry' : ' full'}!
+
+ {
+ this.setState({isHungry: false});
+ }}
+ disabled={!this.state.isHungry}
+ title={
+ this.state.isHungry ? 'Pour me some milk, please!' : 'Thank you!'
+ }
+ />
+
+ );
+ }
+}
+
+class Cafe extends Component {
+ render() {
+ return (
+ <>
+
+
+ >
+ );
+ }
+}
+
+export default Cafe;
+```
+
+
+
+
As always with class components, you must import the `Component` class from React:
-```jsx
-import React, { Component } from 'react';
+```tsx
+import React, {Component} from 'react';
```
In class components, state is stored in a state object:
-```jsx
+```tsx
export class Cat extends Component {
- state = { isHungry: true };
+ state = {isHungry: true};
//..
}
```
As with accessing props with `this.props`, you access this object inside your component with `this.state`:
-```jsx
+```tsx
I am {this.props.name}, and I am
{this.state.isHungry ? ' hungry' : ' full'}!
@@ -488,11 +649,11 @@ As with accessing props with `this.props`, you access this object inside your co
And you set individual values inside the state object by passing an object with the key value pair for state and its new value to `this.setState()`:
-```jsx
+```tsx
{
- this.setState({ isHungry: false });
- }}>
+ this.setState({isHungry: false});
+ }}
// ..
/>
```
@@ -501,7 +662,7 @@ And you set individual values inside the state object by passing an object with
When `this.state.isHungry` is false, the `Button`âs `disabled` prop is set to `true` and its `title` also changes:
-```jsx
+```tsx
{
return (
-
-
- Try editing me! đ
-
+
+ Try editing me! đ
);
-}
+};
export default YourApp;
```
@@ -61,19 +64,20 @@ With React, you can make components using either classes or functions. Originall
```SnackPlayer name=Hello%20World%20Function%20Component
import React from 'react';
-import { Text, View } from 'react-native';
+import {Text, View} from 'react-native';
const HelloWorldApp = () => {
return (
-
+ Hello, world!
);
-}
+};
export default HelloWorldApp;
```
@@ -82,16 +86,17 @@ export default HelloWorldApp;
```SnackPlayer name=Hello%20World%20Class%20Component
-import React, { Component } from 'react';
-import { Text, View } from 'react-native';
+import React, {Component} from 'react';
+import {Text, View} from 'react-native';
class HelloWorldApp extends Component {
render() {
return (
- Hello, world!
diff --git a/docs/javascript-environment.md b/docs/javascript-environment.md
index 293903c6587..97e41683a6e 100644
--- a/docs/javascript-environment.md
+++ b/docs/javascript-environment.md
@@ -7,12 +7,13 @@ import TableRow from '@site/core/TableRowWithCodeBlock';
## JavaScript Runtime
-When using React Native, you're going to be running your JavaScript code in two environments:
+When using React Native, you're going to be running your JavaScript code in up to three 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.
+- In most cases, React Native will use [Hermes](hermes), an open-source JavaScript engine optimized for React Native.
+- If Hermes is disabled, 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.
+While these environments are very similar, you may end up hitting some inconsistencies. It is best to avoid relying on specifics of any runtime.
## JavaScript Syntax Transformers
@@ -28,52 +29,52 @@ A full list of React Native's enabled transformations can be found in [metro-rea
ECMAScript 5
-
+
ECMAScript 2015 (ES6)
-
+
-
-
+
+
-
-
+
+
-
-
-
-
+
+
+
+
-
+
ECMAScript 2016 (ES7)
ECMAScript 2017 (ES8)
-
+
ECMAScript 2018 (ES9)
-
+
ECMAScript 2019 (ES10)
-
+
ECMAScript 2020 (ES11)
ECMAScript 2022 (ES13)
-
+
Stage 1 Proposal
-
+
Miscellaneous
-
+
-
+
diff --git a/docs/keyboard.md b/docs/keyboard.md
index a34971f06d3..78b7a66fe16 100644
--- a/docs/keyboard.md
+++ b/docs/keyboard.md
@@ -15,18 +15,18 @@ The Keyboard module allows you to listen for native events and react to them, as
```SnackPlayer name=Keyboard%20Function%20Component%20Example&supportedPlatforms=ios,android
-import React, { useState, useEffect } from "react";
-import { Keyboard, Text, TextInput, StyleSheet, View } from "react-native";
+import React, {useState, useEffect} from 'react';
+import {Keyboard, Text, TextInput, StyleSheet, View} from 'react-native';
const Example = () => {
- const [keyboardStatus, setKeyboardStatus] = useState(undefined);
+ const [keyboardStatus, setKeyboardStatus] = useState('');
useEffect(() => {
- const showSubscription = Keyboard.addListener("keyboardDidShow", () => {
- setKeyboardStatus("Keyboard Shown");
+ const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
+ setKeyboardStatus('Keyboard Shown');
});
- const hideSubscription = Keyboard.addListener("keyboardDidHide", () => {
- setKeyboardStatus("Keyboard Hidden");
+ const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
+ setKeyboardStatus('Keyboard Hidden');
});
return () => {
@@ -39,28 +39,28 @@ const Example = () => {
{keyboardStatus}
);
-}
+};
const style = StyleSheet.create({
container: {
flex: 1,
- padding: 36
+ padding: 36,
},
input: {
padding: 10,
borderWidth: 0.5,
- borderRadius: 4
+ borderRadius: 4,
},
status: {
padding: 10,
- textAlign: "center"
- }
+ textAlign: 'center',
+ },
});
export default Example;
@@ -69,26 +69,29 @@ export default Example;
-```SnackPlayer name=Keyboard%20Class%20Component%20Example&supportedPlatforms=ios,android
-import React, { Component } from 'react';
-import { Keyboard, Text, TextInput, StyleSheet, View } from 'react-native';
+
+
+
+```SnackPlayer name=Keyboard%20Class%20Component%20Example&supportedPlatforms=ios,android&ext=js
+import React, {Component} from 'react';
+import {Keyboard, Text, TextInput, StyleSheet, View} from 'react-native';
class Example extends Component {
state = {
- keyboardStatus: undefined
+ keyboardStatus: '',
};
componentDidMount() {
this.keyboardDidShowSubscription = Keyboard.addListener(
'keyboardDidShow',
() => {
- this.setState({ keyboardStatus: 'Keyboard Shown' });
+ this.setState({keyboardStatus: 'Keyboard Shown'});
},
);
this.keyboardDidHideSubscription = Keyboard.addListener(
'keyboardDidHide',
() => {
- this.setState({ keyboardStatus: 'Keyboard Hidden' });
+ this.setState({keyboardStatus: 'Keyboard Hidden'});
},
);
}
@@ -103,31 +106,98 @@ class Example extends Component {
-
- {this.state.keyboardStatus}
-
+ {this.state.keyboardStatus}
- )
+ );
}
}
const style = StyleSheet.create({
container: {
flex: 1,
- padding: 36
+ padding: 36,
},
input: {
padding: 10,
borderWidth: 0.5,
- borderRadius: 4
+ borderRadius: 4,
},
status: {
padding: 10,
- textAlign: "center"
+ textAlign: 'center',
+ },
+});
+
+export default Example;
+```
+
+
+
+
+```SnackPlayer name=Keyboard%20Class%20Component%20Example&supportedPlatforms=ios,android&ext=tsx
+import React, {Component} from 'react';
+import {Keyboard, Text, TextInput, StyleSheet, View} from 'react-native';
+import type {EmitterSubscription} from 'react-native';
+
+class Example extends Component {
+ keyboardDidShowSubscription?: EmitterSubscription;
+ keyboardDidHideSubscription?: EmitterSubscription;
+
+ state = {
+ keyboardStatus: undefined,
+ };
+
+ componentDidMount() {
+ this.keyboardDidShowSubscription = Keyboard.addListener(
+ 'keyboardDidShow',
+ () => {
+ this.setState({keyboardStatus: 'Keyboard Shown'});
+ },
+ );
+ this.keyboardDidHideSubscription = Keyboard.addListener(
+ 'keyboardDidHide',
+ () => {
+ this.setState({keyboardStatus: 'Keyboard Hidden'});
+ },
+ );
+ }
+
+ componentWillUnmount() {
+ this.keyboardDidShowSubscription?.remove();
+ this.keyboardDidHideSubscription?.remove();
+ }
+
+ render() {
+ return (
+
+
+ {this.state.keyboardStatus}
+
+ );
}
+}
+
+const style = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 36,
+ },
+ input: {
+ padding: 10,
+ borderWidth: 0.5,
+ borderRadius: 4,
+ },
+ status: {
+ padding: 10,
+ textAlign: 'center',
+ },
});
export default Example;
@@ -136,6 +206,9 @@ export default Example;
+
+
+
---
# Reference
@@ -144,8 +217,11 @@ export default Example;
### `addListener()`
-```jsx
-static addListener(eventName, callback)
+```tsx
+static addListener: (
+ eventType: KeyboardEventName,
+ listener: KeyboardEventListener,
+) => EmitterSubscription;
```
The `addListener` function connects a JavaScript function to an identified native keyboard notification event.
@@ -174,53 +250,40 @@ This can be any of the following:
---
-### `removeListener()`
+### `dismiss()`
-```jsx
-static removeListener(eventName, callback)
+```tsx
+static dismiss();
```
-> **Deprecated.** Use the `remove()` method on the event subscription returned by [`addListener()`](#addlistener).
-
-**Parameters:**
-
-| Name | Type | Required | Description |
-| --------- | -------- | -------- | ------------------------------------------------------------------------------ |
-| eventName | string | Yes | The `nativeEvent` is the string that identifies the event you're listening for |
-| callback | function | Yes | The function to be called when the event fires |
+Dismisses the active keyboard and removes focus.
---
-### `removeAllListeners()`
+### `scheduleLayoutAnimation`
-```jsx
-static removeAllListeners(eventName)
+```tsx
+static scheduleLayoutAnimation(event: KeyboardEvent);
```
-Removes all listeners for a specific event type.
-
-**Parameters:**
-
-| Name | Type | Required | Description |
-| --------- | ------ | -------- | -------------------------------------------------------------------- |
-| eventType | string | Yes | The native event string listeners are watching which will be removed |
+Useful for syncing TextInput (or other keyboard accessory view) size of position changes with keyboard movements.
---
### `dismiss()`
-```jsx
-static dismiss()
+```tsx
+static isVisible(): boolean;
```
-Dismisses the active keyboard and removes focus.
+Whether the keyboard is last known to be visible.
---
-### `scheduleLayoutAnimation`
+### `dismiss()`
-```jsx
-static scheduleLayoutAnimation(event)
+```tsx
+static metrics(): KeyboardMetrics | undefined;
```
-Useful for syncing TextInput (or other keyboard accessory view) size of position changes with keyboard movements.
+Return the metrics of the soft-keyboard if visible.
diff --git a/docs/keyboardavoidingview.md b/docs/keyboardavoidingview.md
index 63af5f4183f..b77375008f8 100644
--- a/docs/keyboardavoidingview.md
+++ b/docs/keyboardavoidingview.md
@@ -9,14 +9,23 @@ This component will automatically adjust its height, position, or bottom padding
```SnackPlayer name=KeyboardAvoidingView&supportedPlatforms=android,ios
import React from 'react';
-import { View, KeyboardAvoidingView, TextInput, StyleSheet, Text, Platform, TouchableWithoutFeedback, Button, Keyboard } from 'react-native';
+import {
+ View,
+ KeyboardAvoidingView,
+ TextInput,
+ StyleSheet,
+ Text,
+ Platform,
+ TouchableWithoutFeedback,
+ Button,
+ Keyboard,
+} from 'react-native';
const KeyboardAvoidingComponent = () => {
return (
+ behavior={Platform.OS === 'ios' ? 'padding' : 'height'}
+ style={styles.container}>
Header
@@ -32,27 +41,27 @@ const KeyboardAvoidingComponent = () => {
const styles = StyleSheet.create({
container: {
- flex: 1
+ flex: 1,
},
inner: {
padding: 24,
flex: 1,
- justifyContent: "space-around"
+ justifyContent: 'space-around',
},
header: {
fontSize: 36,
- marginBottom: 48
+ marginBottom: 48,
},
textInput: {
height: 40,
- borderColor: "#000000",
+ borderColor: '#000000',
borderBottomWidth: 1,
- marginBottom: 36
+ marginBottom: 36,
},
btnContainer: {
- backgroundColor: "white",
- marginTop: 12
- }
+ backgroundColor: 'white',
+ marginTop: 12,
+ },
});
export default KeyboardAvoidingComponent;
diff --git a/docs/layout-props.md b/docs/layout-props.md
index c39be8674cb..3a01a1781e0 100644
--- a/docs/layout-props.md
+++ b/docs/layout-props.md
@@ -3,15 +3,27 @@ id: layout-props
title: Layout Props
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
> More detailed examples about those properties can be found on the [Layout with Flexbox](flexbox) page.
### Example
The following example shows how different properties can affect or shape a React Native layout. You can try for example to add or remove squares from the UI while changing the values of the property `flexWrap`.
-```SnackPlayer name=LayoutProps%20Example
-import React, { useState } from 'react';
-import { Button, ScrollView, StatusBar, StyleSheet, Text, View } from 'react-native';
+
+
+
+```SnackPlayer name=LayoutProps%20Example&ext=js
+import React, {useState} from 'react';
+import {
+ Button,
+ ScrollView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
const App = () => {
const flexDirections = ['row', 'row-reverse', 'column', 'column-reverse'];
@@ -47,7 +59,7 @@ const App = () => {
};
const changeSetting = (value, options, setterFunction) => {
- if (value == options.length - 1) {
+ if (value === options.length - 1) {
setterFunction(0);
return;
}
@@ -56,7 +68,7 @@ const App = () => {
const [squares, setSquares] = useState([, , ]);
return (
<>
-
+
{squares.map(elem => elem)}
@@ -78,7 +90,7 @@ const App = () => {
changeSetting(
justifyContent,
justifyContents,
- setJustifyContent
+ setJustifyContent,
)
}
/>
@@ -110,14 +122,14 @@ const App = () => {
setSquares([...squares, ])}
+ onPress={() => setSquares([...squares, ])}
/>
- setSquares(squares.filter((v, i) => i != squares.length - 1))
+ setSquares(squares.filter((v, i) => i !== squares.length - 1))
}
/>
@@ -145,26 +157,208 @@ const styles = StyleSheet.create({
width: '50%',
padding: 10,
},
- text: { textAlign: 'center' },
+ text: {textAlign: 'center'},
});
const Square = () => (
-
+
);
const randomHexColor = () => {
return '#000000'.replace(/0/g, () => {
- return (~~(Math.random() * 16)).toString(16);
+ return Math.round(Math.random() * 16).toString(16);
});
};
export default App;
```
+
+
+
+```SnackPlayer name=LayoutProps%20Example&ext=tsx
+import React, {useState} from 'react';
+import {
+ Button,
+ ScrollView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+
+const App = () => {
+ const flexDirections = [
+ 'row',
+ 'row-reverse',
+ 'column',
+ 'column-reverse',
+ ] as const;
+ const justifyContents = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'space-between',
+ 'space-around',
+ 'space-evenly',
+ ] as const;
+ const alignItemsArr = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'stretch',
+ 'baseline',
+ ] as const;
+ const wraps = ['nowrap', 'wrap', 'wrap-reverse'] as const;
+ const directions = ['inherit', 'ltr', 'rtl'] as const;
+ const [flexDirection, setFlexDirection] = useState(0);
+ const [justifyContent, setJustifyContent] = useState(0);
+ const [alignItems, setAlignItems] = useState(0);
+ const [direction, setDirection] = useState(0);
+ const [wrap, setWrap] = useState(0);
+
+ const hookedStyles = {
+ flexDirection: flexDirections[flexDirection],
+ justifyContent: justifyContents[justifyContent],
+ alignItems: alignItemsArr[alignItems],
+ direction: directions[direction],
+ flexWrap: wraps[wrap],
+ };
+
+ const changeSetting = (
+ value: number,
+ options: readonly unknown[],
+ setterFunction: (index: number) => void,
+ ) => {
+ if (value === options.length - 1) {
+ setterFunction(0);
+ return;
+ }
+ setterFunction(value + 1);
+ };
+ const [squares, setSquares] = useState([, , ]);
+ return (
+ <>
+
+
+ {squares.map(elem => elem)}
+
+
+
+
+
+ changeSetting(flexDirection, flexDirections, setFlexDirection)
+ }
+ />
+ {flexDirections[flexDirection]}
+
+
+
+ changeSetting(
+ justifyContent,
+ justifyContents,
+ setJustifyContent,
+ )
+ }
+ />
+ {justifyContents[justifyContent]}
+
+
+
+ changeSetting(alignItems, alignItemsArr, setAlignItems)
+ }
+ />
+ {alignItemsArr[alignItems]}
+
+
+ changeSetting(direction, directions, setDirection)}
+ />
+ {directions[direction]}
+
+
+ changeSetting(wrap, wraps, setWrap)}
+ />
+ {wraps[wrap]}
+
+
+ setSquares([...squares, ])}
+ />
+
+
+
+ setSquares(squares.filter((v, i) => i !== squares.length - 1))
+ }
+ />
+
+
+
+ >
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ height: '50%',
+ },
+ playingSpace: {
+ backgroundColor: 'white',
+ borderColor: 'blue',
+ borderWidth: 3,
+ },
+ controlSpace: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ backgroundColor: '#F5F5F5',
+ },
+ buttonView: {
+ width: '50%',
+ padding: 10,
+ },
+ text: {textAlign: 'center'},
+});
+
+const Square = () => (
+
+);
+
+const randomHexColor = () => {
+ return '#000000'.replace(/0/g, () => {
+ return Math.round(Math.random() * 16).toString(16);
+ });
+};
+
+export default App;
+```
+
+
+
+
---
# Reference
@@ -301,6 +495,16 @@ See https://developer.mozilla.org/en-US/docs/Web/CSS/bottom for more details of
---
+### `columnGap`
+
+`columnGap` works like `column-gap` in CSS. Only pixel units are supported in React Native. See https://developer.mozilla.org/en-US/docs/Web/CSS/column-gap for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
### `direction`
`direction` specifies the directional flow of the user interface. The default is `inherit`, except for root node which will have value based on the current locale. See https://yogalayout.com/docs/layout-direction for more details.
@@ -407,6 +611,16 @@ When `flex` is -1, the component is normally sized according to `width` and `hei
---
+### `gap`
+
+`gap` works like `gap` in CSS. Only pixel units are supported in React Native. See https://developer.mozilla.org/en-US/docs/Web/CSS/gap for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
### `height`
`height` sets the height of this component.
@@ -719,6 +933,16 @@ See https://developer.mozilla.org/en-US/docs/Web/CSS/right for more details of h
---
+### `rowGap`
+
+`rowGap` works like `row-gap` in CSS. Only pixel units are supported in React Native. See https://developer.mozilla.org/en-US/docs/Web/CSS/row-gap for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
### `start`
When the direction is `ltr`, `start` is equivalent to `left`. When the direction is `rtl`, `start` is equivalent to `right`.
diff --git a/docs/layoutanimation.md b/docs/layoutanimation.md
index 10da37ba67d..7afa98c7659 100644
--- a/docs/layoutanimation.md
+++ b/docs/layoutanimation.md
@@ -22,11 +22,19 @@ if (Platform.OS === 'android') {
## Example
```SnackPlayer name=LayoutAnimation&supportedPlatforms=android,ios
-import React, { useState } from "react";
-import { LayoutAnimation, Platform, StyleSheet, Text, TouchableOpacity, UIManager, View } from "react-native";
+import React, {useState} from 'react';
+import {
+ LayoutAnimation,
+ Platform,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ UIManager,
+ View,
+} from 'react-native';
if (
- Platform.OS === "android" &&
+ Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
@@ -40,9 +48,8 @@ const App = () => {
onPress={() => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
setExpanded(!expanded);
- }}
- >
- Press me to {expanded ? "collapse" : "expand"}!
+ }}>
+ Press me to {expanded ? 'collapse' : 'expand'}!
{expanded && (
@@ -55,16 +62,16 @@ const App = () => {
const style = StyleSheet.create({
tile: {
- backgroundColor: "lightgrey",
+ backgroundColor: 'lightgrey',
borderWidth: 0.5,
- borderColor: "#d6d7da"
+ borderColor: '#d6d7da',
},
container: {
flex: 1,
- justifyContent: "center",
- alignItems: "center",
- overflow: "hidden"
- }
+ justifyContent: 'center',
+ alignItems: 'center',
+ overflow: 'hidden',
+ },
});
export default App;
@@ -78,8 +85,12 @@ export default App;
### `configureNext()`
-```jsx
-static configureNext(config, onAnimationDidEnd?, onAnimationDidFail?)
+```tsx
+static configureNext(
+ config: LayoutAnimationConfig,
+ onAnimationDidEnd?: () => void,
+ onAnimationDidFail?: () => void,
+);
```
Schedules an animation to happen on the next layout.
@@ -112,7 +123,7 @@ The config that's passed to `create`, `update`, or `delete` has the following ke
### `create()`
-```jsx
+```tsx
static create(duration, type, creationProp)
```
@@ -124,34 +135,34 @@ Helper that creates an object (with `create`, `update`, and `delete` fields) to
```SnackPlayer name=LayoutAnimation&supportedPlatforms=android,ios
-import React, { useState } from "react";
+import React, {useState} from 'react';
import {
View,
Platform,
UIManager,
LayoutAnimation,
StyleSheet,
- Button
-} from "react-native";
+ Button,
+} from 'react-native';
if (
- Platform.OS === "android" &&
+ Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
const App = () => {
- const [boxPosition, setBoxPosition] = useState("left");
+ const [boxPosition, setBoxPosition] = useState('left');
const toggleBox = () => {
LayoutAnimation.configureNext({
duration: 500,
- create: { type: "linear", property: "opacity" },
- update: { type: "spring", springDamping: 0.4 },
- delete: { type: "linear", property: "opacity" }
+ create: {type: 'linear', property: 'opacity'},
+ update: {type: 'spring', springDamping: 0.4},
+ delete: {type: 'linear', property: 'opacity'},
});
- setBoxPosition(boxPosition === "left" ? "right" : "left");
+ setBoxPosition(boxPosition === 'left' ? 'right' : 'left');
};
return (
@@ -160,33 +171,33 @@ const App = () => {
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "flex-start",
- justifyContent: "center"
+ alignItems: 'flex-start',
+ justifyContent: 'center',
},
box: {
height: 100,
width: 100,
borderRadius: 5,
margin: 8,
- backgroundColor: "blue"
+ backgroundColor: 'blue',
},
moveRight: {
- alignSelf: "flex-end",
+ alignSelf: 'flex-end',
height: 200,
- width: 200
+ width: 200,
},
buttonContainer: {
- alignSelf: "center"
- }
+ alignSelf: 'center',
+ },
});
export default App;
@@ -196,18 +207,18 @@ export default App;
```SnackPlayer name=LayoutAnimation&supportedPlatforms=android,ios
-import React, { Component } from "react";
+import React, {Component} from 'react';
import {
View,
Platform,
UIManager,
LayoutAnimation,
StyleSheet,
- Button
-} from "react-native";
+ Button,
+} from 'react-native';
if (
- Platform.OS === "android" &&
+ Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
@@ -215,18 +226,18 @@ if (
class App extends Component {
state = {
- boxPosition: "left"
+ boxPosition: 'left',
};
toggleBox = () => {
LayoutAnimation.configureNext({
duration: 500,
- create: { type: "linear", property: "opacity" },
- update: { type: "spring", springDamping: 0.4 },
- delete: { type: "linear", property: "opacity" }
+ create: {type: 'linear', property: 'opacity'},
+ update: {type: 'spring', springDamping: 0.4},
+ delete: {type: 'linear', property: 'opacity'},
});
this.setState({
- boxPosition: this.state.boxPosition === "left" ? "right" : "left"
+ boxPosition: this.state.boxPosition === 'left' ? 'right' : 'left',
});
};
@@ -239,7 +250,7 @@ class App extends Component {
@@ -250,24 +261,24 @@ class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "flex-start",
- justifyContent: "center"
+ alignItems: 'flex-start',
+ justifyContent: 'center',
},
box: {
height: 100,
width: 100,
borderRadius: 5,
margin: 8,
- backgroundColor: "blue"
+ backgroundColor: 'blue',
},
moveRight: {
- alignSelf: "flex-end",
+ alignSelf: 'flex-end',
height: 200,
- width: 200
+ width: 200,
},
buttonContainer: {
- alignSelf: "center"
- }
+ alignSelf: 'center',
+ },
});
export default App;
@@ -310,11 +321,11 @@ An enumeration of layout properties to be animated to be used in the [`create`](
A set of predefined animation configs to pass into [`configureNext`](layoutanimation.md#configurenext).
-| Presets | Value |
-| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| easeInEaseOut | `create(300, 'easeInEaseOut', 'opacity')` |
-| linear | `create(500, 'linear', 'opacity')` |
-| spring | `{ duration: 700, create: { type: 'linear', property: 'opacity' }, update: { type: 'spring', springDamping: 0.4 }, delete: { type: 'linear', property: 'opacity' } }` |
+| Presets | Value |
+| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| easeInEaseOut | `create(300, 'easeInEaseOut', 'opacity')` |
+| linear | `create(500, 'linear', 'opacity')` |
+| spring | `{duration: 700, create: {type: 'linear', property: 'opacity'}, update: {type: 'spring', springDamping: 0.4}, delete: {type: 'linear', property: 'opacity'} }` |
---
@@ -340,41 +351,41 @@ Calls `configureNext()` with `Presets.spring`.
```SnackPlayer name=LayoutAnimation&supportedPlatforms=android,ios
-import React, { useState } from "react";
+import React, {useState} from 'react';
import {
View,
Platform,
UIManager,
LayoutAnimation,
StyleSheet,
- Button
-} from "react-native";
+ Button,
+} from 'react-native';
if (
- Platform.OS === "android" &&
+ Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
}
const App = () => {
- const [firstBoxPosition, setFirstBoxPosition] = useState("left");
- const [secondBoxPosition, setSecondBoxPosition] = useState("left");
- const [thirdBoxPosition, setThirdBoxPosition] = useState("left");
+ const [firstBoxPosition, setFirstBoxPosition] = useState('left');
+ const [secondBoxPosition, setSecondBoxPosition] = useState('left');
+ const [thirdBoxPosition, setThirdBoxPosition] = useState('left');
const toggleFirstBox = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
- setFirstBoxPosition(firstBoxPosition === "left" ? "right" : "left");
+ setFirstBoxPosition(firstBoxPosition === 'left' ? 'right' : 'left');
};
const toggleSecondBox = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
- setSecondBoxPosition(secondBoxPosition === "left" ? "right" : "left");
+ setSecondBoxPosition(secondBoxPosition === 'left' ? 'right' : 'left');
};
const toggleThirdBox = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
- setThirdBoxPosition(thirdBoxPosition === "left" ? "right" : "left");
+ setThirdBoxPosition(thirdBoxPosition === 'left' ? 'right' : 'left');
};
return (
@@ -385,7 +396,7 @@ const App = () => {
@@ -394,7 +405,7 @@ const App = () => {
@@ -403,32 +414,32 @@ const App = () => {
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "flex-start",
- justifyContent: "center"
+ alignItems: 'flex-start',
+ justifyContent: 'center',
},
box: {
height: 100,
width: 100,
borderRadius: 5,
margin: 8,
- backgroundColor: "blue"
+ backgroundColor: 'blue',
},
moveRight: {
- alignSelf: "flex-end"
+ alignSelf: 'flex-end',
},
buttonContainer: {
- alignSelf: "center"
- }
+ alignSelf: 'center',
+ },
});
export default App;
@@ -438,18 +449,18 @@ export default App;
```SnackPlayer name=LayoutAnimation&supportedPlatforms=android,ios
-import React, { Component } from "react";
+import React, {Component} from 'react';
import {
View,
Platform,
UIManager,
LayoutAnimation,
StyleSheet,
- Button
-} from "react-native";
+ Button,
+} from 'react-native';
if (
- Platform.OS === "android" &&
+ Platform.OS === 'android' &&
UIManager.setLayoutAnimationEnabledExperimental
) {
UIManager.setLayoutAnimationEnabledExperimental(true);
@@ -457,16 +468,16 @@ if (
class App extends Component {
state = {
- firstBoxPosition: "left",
- secondBoxPosition: "left",
- thirdBoxPosition: "left"
+ firstBoxPosition: 'left',
+ secondBoxPosition: 'left',
+ thirdBoxPosition: 'left',
};
toggleFirstBox = () => {
LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
this.setState({
firstBoxPosition:
- this.state.firstBoxPosition === "left" ? "right" : "left"
+ this.state.firstBoxPosition === 'left' ? 'right' : 'left',
});
};
@@ -474,7 +485,7 @@ class App extends Component {
LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
this.setState({
secondBoxPosition:
- this.state.secondBoxPosition === "left" ? "right" : "left"
+ this.state.secondBoxPosition === 'left' ? 'right' : 'left',
});
};
@@ -482,7 +493,7 @@ class App extends Component {
LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
this.setState({
thirdBoxPosition:
- this.state.thirdBoxPosition === "left" ? "right" : "left"
+ this.state.thirdBoxPosition === 'left' ? 'right' : 'left',
});
};
@@ -495,7 +506,7 @@ class App extends Component {
@@ -504,7 +515,7 @@ class App extends Component {
@@ -513,7 +524,7 @@ class App extends Component {
@@ -524,22 +535,22 @@ class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "flex-start",
- justifyContent: "center"
+ alignItems: 'flex-start',
+ justifyContent: 'center',
},
box: {
height: 100,
width: 100,
borderRadius: 5,
margin: 8,
- backgroundColor: "blue"
+ backgroundColor: 'blue',
},
moveRight: {
- alignSelf: "flex-end"
+ alignSelf: 'flex-end',
},
buttonContainer: {
- alignSelf: "center"
- }
+ alignSelf: 'center',
+ },
});
export default App;
diff --git a/docs/libraries.md b/docs/libraries.md
index e8c1a10bcf1..abecb19b5a6 100644
--- a/docs/libraries.md
+++ b/docs/libraries.md
@@ -6,7 +6,7 @@ authorURL: 'https://twitter.com/notbrent'
description: This guide introduces React Native developers to finding, installing, and using third-party libraries in their apps.
---
-import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; import M1Cocoapods from './\_markdown-m1-cocoapods.mdx';
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
React Native provides a set of built-in [Core Components and APIs](./components-and-apis) ready to use in your app. You're not limited to the components and APIs bundled with React Native. React Native has a community of thousands of developers. If the Core Components and APIs don't have what you are looking for, you may be able to find and install a library from the community to add the functionality to your app.
@@ -51,8 +51,6 @@ Run `pod install` in our `ios` directory in order to link it to our native iOS p
npx pod-install
```
-
-
Once this is complete, re-build the app binary to start using your new library:
```bash
diff --git a/docs/linking.md b/docs/linking.md
index a37c3d9c15c..fcfc55e951e 100644
--- a/docs/linking.md
+++ b/docs/linking.md
@@ -102,7 +102,7 @@ There are two ways to handle URLs that open your app.
#### 1. If the app is already open, the app is foregrounded and a Linking 'url' event is fired
-You can handle these events with `Linking.addEventListener('url', callback)` - it calls `callback({ url })` with the linked URL
+You can handle these events with `Linking.addEventListener('url', callback)` - it calls `callback({url})` with the linked URL
#### 2. If the app is not already open, it is opened and the url is passed in as the initialURL
@@ -114,15 +114,71 @@ You can handle these events with `Linking.getInitialURL()` - it returns a Promis
### Open Links and Deep Links (Universal Links)
-```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android
-import React, { useCallback } from "react";
-import { Alert, Button, Linking, StyleSheet, View } from "react-native";
+
+
-const supportedURL = "https://google.com";
+```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android&ext=js
+import React, {useCallback} from 'react';
+import {Alert, Button, Linking, StyleSheet, View} from 'react-native';
-const unsupportedURL = "slack://open?team=123456";
+const supportedURL = 'https://google.com';
-const OpenURLButton = ({ url, children }) => {
+const unsupportedURL = 'slack://open?team=123456';
+
+const OpenURLButton = ({url, children}) => {
+ const handlePress = useCallback(async () => {
+ // Checking if the link is supported for links with custom URL scheme.
+ const supported = await Linking.canOpenURL(url);
+
+ if (supported) {
+ // Opening the link with some app, if the URL scheme is "http" the web link should be opened
+ // by some browser in the mobile
+ await Linking.openURL(url);
+ } else {
+ Alert.alert(`Don't know how to open this URL: ${url}`);
+ }
+ }, [url]);
+
+ return ;
+};
+
+const App = () => {
+ return (
+
+ Open Supported URL
+ Open Unsupported URL
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android&ext=tsx
+import React, {useCallback} from 'react';
+import {Alert, Button, Linking, StyleSheet, View} from 'react-native';
+
+const supportedURL = 'https://google.com';
+
+const unsupportedURL = 'slack://open?team=123456';
+
+type OpenURLButtonProps = {
+ url: string;
+ children: string;
+};
+
+const OpenURLButton = ({url, children}: OpenURLButtonProps) => {
const handlePress = useCallback(async () => {
// Checking if the link is supported for links with custom URL scheme.
const supported = await Linking.canOpenURL(url);
@@ -149,19 +205,68 @@ const App = () => {
};
const styles = StyleSheet.create({
- container: { flex: 1, justifyContent: "center", alignItems: "center" },
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
});
export default App;
```
+
+
+
### Open Custom Settings
-```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android
-import React, { useCallback } from "react";
-import { Button, Linking, StyleSheet, View } from "react-native";
+
+
+
+```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android&ext=js
+import React, {useCallback} from 'react';
+import {Button, Linking, StyleSheet, View} from 'react-native';
+
+const OpenSettingsButton = ({children}) => {
+ const handlePress = useCallback(async () => {
+ // Open the custom settings if the app has one
+ await Linking.openSettings();
+ }, []);
+
+ return ;
+};
+
+const App = () => {
+ return (
+
+ Open Settings
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android&ext=tsx
+import React, {useCallback} from 'react';
+import {Button, Linking, StyleSheet, View} from 'react-native';
+
+type OpenSettingsButtonProps = {
+ children: string;
+};
-const OpenSettingsButton = ({ children }) => {
+const OpenSettingsButton = ({children}: OpenSettingsButtonProps) => {
const handlePress = useCallback(async () => {
// Open the custom settings if the app has one
await Linking.openSettings();
@@ -179,25 +284,87 @@ const App = () => {
};
const styles = StyleSheet.create({
- container: { flex: 1, justifyContent: "center", alignItems: "center" },
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
});
export default App;
```
+
+
+
### Get the Deep Link
-```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android
-import React, { useState, useEffect } from "react";
-import { Linking, StyleSheet, Text, View } from "react-native";
+
+
-const useMount = func => useEffect(() => func(), []);
+```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android&ext=js
+import React, {useState, useEffect} from 'react';
+import {Linking, StyleSheet, Text, View} from 'react-native';
const useInitialURL = () => {
const [url, setUrl] = useState(null);
const [processing, setProcessing] = useState(true);
- useMount(() => {
+ useEffect(() => {
+ const getUrlAsync = async () => {
+ // Get the deep link used to open the app
+ const initialUrl = await Linking.getInitialURL();
+
+ // The setTimeout is just for testing purpose
+ setTimeout(() => {
+ setUrl(initialUrl);
+ setProcessing(false);
+ }, 1000);
+ };
+
+ getUrlAsync();
+ }, []);
+
+ return {url, processing};
+};
+
+const App = () => {
+ const {url: initialUrl, processing} = useInitialURL();
+
+ return (
+
+
+ {processing
+ ? 'Processing the initial url from a deep link'
+ : `The deep link is: ${initialUrl || 'None'}`}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=ios,android&ext=tsx
+import React, {useState, useEffect} from 'react';
+import {Linking, StyleSheet, Text, View} from 'react-native';
+
+const useInitialURL = () => {
+ const [url, setUrl] = useState(null);
+ const [processing, setProcessing] = useState(true);
+
+ useEffect(() => {
const getUrlAsync = async () => {
// Get the deep link used to open the app
const initialUrl = await Linking.getInitialURL();
@@ -210,39 +377,49 @@ const useInitialURL = () => {
};
getUrlAsync();
- });
+ }, []);
- return { url, processing };
+ return {url, processing};
};
const App = () => {
- const { url: initialUrl, processing } = useInitialURL();
+ const {url: initialUrl, processing} = useInitialURL();
return (
{processing
- ? `Processing the initial url from a deep link`
- : `The deep link is: ${initialUrl || "None"}`}
+ ? 'Processing the initial url from a deep link'
+ : `The deep link is: ${initialUrl || 'None'}`}
);
};
const styles = StyleSheet.create({
- container: { flex: 1, justifyContent: "center", alignItems: "center" },
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
});
export default App;
```
+
+
+
### Send Intents (Android)
-```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=android
-import React, { useCallback } from "react";
-import { Alert, Button, Linking, StyleSheet, View } from "react-native";
+
+
+
+```SnackPlayer name=Linking%20Function%20Component%20Example&supportedPlatforms=android&ext=js
+import React, {useCallback} from 'react';
+import {Alert, Button, Linking, StyleSheet, View} from 'react-native';
-const SendIntentButton = ({ action, extras, children }) => {
+const SendIntentButton = ({action, extras, children}) => {
const handlePress = useCallback(async () => {
try {
await Linking.sendIntent(action, extras);
@@ -263,9 +440,74 @@ const App = () => {
+ {
+ key: 'android.provider.extra.APP_PACKAGE',
+ value: 'com.facebook.katana',
+ },
+ ]}>
+ App Notification Settings
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Linking%20Function%20Component%20Example&ext=tsx
+import React, {useCallback} from 'react';
+import {Alert, Button, Linking, StyleSheet, View} from 'react-native';
+
+type SendIntentButtonProps = {
+ action: string;
+ children: string;
+ extras?: Array<{
+ key: string;
+ value: string | number | boolean;
+ }>;
+};
+
+const SendIntentButton = ({
+ action,
+ extras,
+ children,
+}: SendIntentButtonProps) => {
+ const handlePress = useCallback(async () => {
+ try {
+ await Linking.sendIntent(action, extras);
+ } catch (e: any) {
+ Alert.alert(e.message);
+ }
+ }, [action, extras]);
+
+ return ;
+};
+
+const App = () => {
+ return (
+
+
+ Power Usage Summary
+
+
App Notification Settings
@@ -273,20 +515,30 @@ const App = () => {
};
const styles = StyleSheet.create({
- container: { flex: 1, justifyContent: "center", alignItems: "center" },
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
});
export default App;
```
+
+
+
# Reference
## Methods
### `addEventListener()`
-```jsx
-addEventListener(type, handler);
+```tsx
+static addEventListener(
+ type: 'url',
+ handler: (event: {url: string}) => void,
+): EmitterSubscription;
```
Add a handler to Linking changes by listening to the `url` event type and providing the handler.
@@ -295,8 +547,8 @@ Add a handler to Linking changes by listening to the `url` event type and provid
### `canOpenURL()`
-```jsx
-canOpenURL(url);
+```tsx
+static canOpenURL(url: string): Promise;
```
Determine whether or not an installed app can handle a given URL.
@@ -338,8 +590,8 @@ The `Promise` will reject on Android if it was impossible to check if the URL ca
### `getInitialURL()`
-```jsx
-getInitialURL();
+```tsx
+static getInitialURL(): Promise;
```
If the app launch was triggered by an app link, it will give the link url, otherwise it will give `null`.
@@ -352,8 +604,8 @@ If the app launch was triggered by an app link, it will give the link url, other
### `openSettings()`
-```jsx
-openSettings();
+```tsx
+static openSettings(): Promise;
```
Open the Settings app and displays the appâs custom settings, if it has any.
@@ -362,8 +614,8 @@ Open the Settings app and displays the appâs custom settings, if it has any.
### `openURL()`
-```jsx
-openURL(url);
+```tsx
+static openURL(url: string): Promise;
```
Try to open the given `url` with any of the installed apps.
@@ -386,20 +638,13 @@ The method returns a `Promise` object. If the user confirms the open dialog or t
---
-### `removeEventListener()`
-
-```jsx
-removeEventListener(type, handler);
-```
-
-> **Deprecated.** Use the `remove()` method on the event subscription returned by [`addEventListener()`](#addeventlistener).
-
----
-
### `sendIntent()`
Android
-```jsx
-sendIntent(action, extras);
+```tsx
+static sendIntent(
+ action: string,
+ extras?: Array<{key: string; value: string | number | boolean}>,
+): Promise;
```
Launch an Android intent with extras.
diff --git a/docs/modal.md b/docs/modal.md
index bc461ae7af9..46db5921f3f 100644
--- a/docs/modal.md
+++ b/docs/modal.md
@@ -13,8 +13,8 @@ The Modal component is a basic way to present content above an enclosing view.
```SnackPlayer name=Modal&supportedPlatforms=android,ios
-import React, { useState } from "react";
-import { Alert, Modal, StyleSheet, Text, Pressable, View } from "react-native";
+import React, {useState} from 'react';
+import {Alert, Modal, StyleSheet, Text, Pressable, View} from 'react-native';
const App = () => {
const [modalVisible, setModalVisible] = useState(false);
@@ -25,17 +25,15 @@ const App = () => {
transparent={true}
visible={modalVisible}
onRequestClose={() => {
- Alert.alert("Modal has been closed.");
+ Alert.alert('Modal has been closed.');
setModalVisible(!modalVisible);
- }}
- >
+ }}>
Hello World! setModalVisible(!modalVisible)}
- >
+ onPress={() => setModalVisible(!modalVisible)}>
Hide Modal
@@ -43,8 +41,7 @@ const App = () => {
setModalVisible(true)}
- >
+ onPress={() => setModalVisible(true)}>
Show Modal
@@ -54,45 +51,45 @@ const App = () => {
const styles = StyleSheet.create({
centeredView: {
flex: 1,
- justifyContent: "center",
- alignItems: "center",
- marginTop: 22
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginTop: 22,
},
modalView: {
margin: 20,
- backgroundColor: "white",
+ backgroundColor: 'white',
borderRadius: 20,
padding: 35,
- alignItems: "center",
- shadowColor: "#000",
+ alignItems: 'center',
+ shadowColor: '#000',
shadowOffset: {
width: 0,
- height: 2
+ height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
- elevation: 5
+ elevation: 5,
},
button: {
borderRadius: 20,
padding: 10,
- elevation: 2
+ elevation: 2,
},
buttonOpen: {
- backgroundColor: "#F194FF",
+ backgroundColor: '#F194FF',
},
buttonClose: {
- backgroundColor: "#2196F3",
+ backgroundColor: '#2196F3',
},
textStyle: {
- color: "white",
- fontWeight: "bold",
- textAlign: "center"
+ color: 'white',
+ fontWeight: 'bold',
+ textAlign: 'center',
},
modalText: {
marginBottom: 15,
- textAlign: "center"
- }
+ textAlign: 'center',
+ },
});
export default App;
@@ -102,20 +99,16 @@ export default App;
```SnackPlayer name=Modal&supportedPlatforms=android,ios
-import React, { Component } from "react";
-import { Alert, Modal, StyleSheet, Text, Pressable, View } from "react-native";
+import React, {Component} from 'react';
+import {Alert, Modal, StyleSheet, Text, Pressable, View} from 'react-native';
class App extends Component {
state = {
- modalVisible: false
+ modalVisible: false,
};
- setModalVisible = (visible) => {
- this.setState({ modalVisible: visible });
- }
-
render() {
- const { modalVisible } = this.state;
+ const {modalVisible} = this.state;
return (
{
- Alert.alert("Modal has been closed.");
- this.setModalVisible(!modalVisible);
- }}
- >
+ Alert.alert('Modal has been closed.');
+ this.setState({modalVisible: !modalVisible});
+ }}>
Hello World! this.setModalVisible(!modalVisible)}
- >
+ onPress={() => this.setState({modalVisible: !modalVisible})}>
Hide Modal
@@ -141,8 +132,7 @@ class App extends Component {
this.setModalVisible(true)}
- >
+ onPress={() => this.setState({modalVisible: true})}>
Show Modal
@@ -153,45 +143,45 @@ class App extends Component {
const styles = StyleSheet.create({
centeredView: {
flex: 1,
- justifyContent: "center",
- alignItems: "center",
- marginTop: 22
+ justifyContent: 'center',
+ alignItems: 'center',
+ marginTop: 22,
},
modalView: {
margin: 20,
- backgroundColor: "white",
+ backgroundColor: 'white',
borderRadius: 20,
padding: 35,
- alignItems: "center",
- shadowColor: "#000",
+ alignItems: 'center',
+ shadowColor: '#000',
shadowOffset: {
width: 0,
- height: 2
+ height: 2,
},
shadowOpacity: 0.25,
shadowRadius: 4,
- elevation: 5
+ elevation: 5,
},
button: {
borderRadius: 20,
padding: 10,
- elevation: 2
+ elevation: 2,
},
buttonOpen: {
- backgroundColor: "#F194FF",
+ backgroundColor: '#F194FF',
},
buttonClose: {
- backgroundColor: "#2196F3",
+ backgroundColor: '#2196F3',
},
textStyle: {
- color: "white",
- fontWeight: "bold",
- textAlign: "center"
+ color: 'white',
+ fontWeight: 'bold',
+ textAlign: 'center',
},
modalText: {
marginBottom: 15,
- textAlign: "center"
- }
+ textAlign: 'center',
+ },
});
export default App;
diff --git a/docs/more-resources.md b/docs/more-resources.md
index 4f99b29bdaa..c9c4aa647d5 100644
--- a/docs/more-resources.md
+++ b/docs/more-resources.md
@@ -28,7 +28,7 @@ We recommend using the [VS Code](https://code.visualstudio.com/) code editor and
[Expo](https://docs.expo.dev/) is a framework of tools and services for React Native that focuses on helping you build, ship, and iterate on your app, to use preview deployment workflows that are popular with web development, and to automate your development workflows. Expo also makes it possible to build React Native apps without ever touching Xcode or Android Studio, and it doesn't get in the way if you want to use those tools.
-[Ignite](https://github.com/infinitered/ignite) is a starter kit CLI with several React Native boilerplates. The latest, [Ignite Bowser](https://github.com/infinitered/ignite-bowser), uses MobX-State-Tree for state management, React Navigation, and other common libraries. It has generators for components, models, and more, and supports Expo out of the box. If you are looking for a preconfigured tech stack, Ignite could be perfect for you.
+[Ignite](https://github.com/infinitered/ignite) is a starter kit CLI with several React Native boilerplates. The latest, Ignite Maverick, uses MobX-State-Tree for state management, React Navigation, and other common libraries.It has generators for screens, models, and more, and supports Expo out of the box. Ignite also comes with a component library that is tuned for custom designs, theming support, and testing. If you are looking for a preconfigured tech stack, Ignite could be perfect for you.
## Example Apps
diff --git a/docs/native-components-android.md b/docs/native-components-android.md
index 51b2e302678..985734cfe14 100644
--- a/docs/native-components-android.md
+++ b/docs/native-components-android.md
@@ -180,10 +180,10 @@ The final step is to register the ViewManager to the application, this happens i
### 5. Implement the JavaScript module
-The very final step is to create the JavaScript module that defines the interface layer between Java/Kotlin and JavaScript for the users of your new view. It is recommended for you to document the component interface in this module (e.g. using Flow, TypeScript, or plain old comments).
+The very final step is to create the JavaScript module that defines the interface layer between Java/Kotlin and JavaScript for the users of your new view. It is recommended for you to document the component interface in this module (e.g. using TypeScript, Flow, or plain old comments).
-```jsx title="ImageView.js"
-import { requireNativeComponent } from 'react-native';
+```tsx title="ImageView.tsx"
+import {requireNativeComponent} from 'react-native';
/**
* Composes `View`.
@@ -282,7 +282,7 @@ public class ReactImageManager extends SimpleViewManager {
This callback is invoked with the raw event, which we typically process in the wrapper component to make a simpler API:
-```jsx title="MyCustomView.js"
+```tsx title="MyCustomView.tsx"
class MyCustomView extends React.Component {
constructor(props) {
super(props);
@@ -815,8 +815,8 @@ public class MyPackage implements ReactPackage {
I. Start with custom View manager:
-```jsx title="MyViewManager.jsx"
-import { requireNativeComponent } from 'react-native';
+```tsx title="MyViewManager.tsx"
+import {requireNativeComponent} from 'react-native';
export const MyViewManager =
requireNativeComponent('MyViewManager');
@@ -824,22 +824,22 @@ export const MyViewManager =
II. Then implement custom View calling the `create` method:
-```jsx title="MyView.jsx"
-import React, { useEffect, useRef } from 'react';
+```tsx title="MyView.tsx"
+import React, {useEffect, useRef} from 'react';
import {
PixelRatio,
UIManager,
- findNodeHandle
+ findNodeHandle,
} from 'react-native';
-import { MyViewManager } from './my-view-manager';
+import {MyViewManager} from './my-view-manager';
-const createFragment = (viewId) =>
+const createFragment = viewId =>
UIManager.dispatchViewManagerCommand(
viewId,
// we are calling the 'create' command
UIManager.MyViewManager.Commands.create.toString(),
- [viewId]
+ [viewId],
);
export const MyView = () => {
@@ -856,7 +856,7 @@ export const MyView = () => {
// converts dpi to px, provide desired height
height: PixelRatio.getPixelSizeForLayoutSize(200),
// converts dpi to px, provide desired width
- width: PixelRatio.getPixelSizeForLayoutSize(200)
+ width: PixelRatio.getPixelSizeForLayoutSize(200),
}}
ref={ref}
/>
diff --git a/docs/native-components-ios.md b/docs/native-components-ios.md
index bba1b3559f6..48eb181d660 100644
--- a/docs/native-components-ios.md
+++ b/docs/native-components-ios.md
@@ -57,20 +57,20 @@ Apple frameworks use two-letter prefixes, and React Native uses `RCT` as a prefi
Then you need a little bit of JavaScript to make this a usable React component:
-```jsx title='MapView.js'
-import { requireNativeComponent } from 'react-native';
+```tsx title="MapView.tsx"
+import {requireNativeComponent} from 'react-native';
// requireNativeComponent automatically resolves 'RNTMap' to 'RNTMapManager'
module.exports = requireNativeComponent('RNTMap');
```
-```jsx title='MyApp.js'
+```tsx title="MyApp.tsx"
import MapView from './MapView.js';
...
render() {
- return ;
+ return ;
}
```
@@ -80,7 +80,7 @@ Make sure to use `RNTMap` here. We want to require the manager here, which will
When rendering, don't forget to stretch the view, otherwise you'll be staring at a blank screen.
:::
-```jsx
+```tsx
render() {
return ;
}
@@ -100,16 +100,16 @@ Note that we explicitly specify the type as `BOOL` - React Native uses `RCTConve
Now to actually disable zooming, we set the property in JS:
-```jsx title='MyApp.js'
-
+```tsx title="MyApp.tsx"
+
```
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 title='MapView.js'
+```tsx title="MapView.tsx"
import PropTypes from 'prop-types';
import React from 'react';
-import { requireNativeComponent } from 'react-native';
+import {requireNativeComponent} from 'react-native';
class MapView extends React.Component {
render() {
@@ -122,7 +122,7 @@ 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
+ zoomEnabled: PropTypes.bool,
};
var RNTMap = requireNativeComponent('RNTMap');
@@ -188,7 +188,7 @@ These conversion functions are designed to safely process any JSON that the JS m
To finish up support for the `region` prop, we need to document it in `propTypes`:
-```jsx title='MapView.js'
+```tsx title="MapView.tsx"
MapView.propTypes = {
/**
* A Boolean value that determines whether the user may use pinch
@@ -214,12 +214,12 @@ MapView.propTypes = {
* to be displayed.
*/
latitudeDelta: PropTypes.number.isRequired,
- longitudeDelta: PropTypes.number.isRequired
- })
+ longitudeDelta: PropTypes.number.isRequired,
+ }),
};
```
-```jsx title='MyApp.js'
+```tsx title="MyApp.tsx"
render() {
var region = {
latitude: 37.48,
@@ -231,7 +231,7 @@ render() {
);
}
@@ -319,9 +319,9 @@ RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
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 simplify the API:
-```jsx title='MapView.js'
+```tsx title="MapView.tsx"
class MapView extends React.Component {
- _onRegionChange = (event) => {
+ _onRegionChange = event => {
if (!this.props.onRegionChange) {
return;
}
@@ -347,7 +347,7 @@ MapView.propTypes = {
};
```
-```jsx title='MyApp.js'
+```tsx title="MyApp.tsx"
class MyApp extends React.Component {
onRegionChange(event) {
// Do stuff with event.region.latitude, etc.
@@ -358,7 +358,7 @@ class MyApp extends React.Component {
latitude: 37.48,
longitude: -122.16,
latitudeDelta: 0.1,
- longitudeDelta: 0.1
+ longitudeDelta: 0.1,
};
return (
@@ -387,7 +387,7 @@ In this example, the class `MyNativeView` is a wrapper for a `NativeComponent` a
When the user interacts with the component, like clicking the button, the `backgroundColor` of `MyNativeView` changes. In this case `UIManager` would not know which `MyNativeView` should be handled and which one should change `backgroundColor`. Below you will find a solution to this problem:
-```jsx
+```tsx
@@ -401,14 +401,14 @@ When the user interacts with the component, like clicking the button, the `backg
Now the above component has a reference to a particular `MyNativeView` which allows us to use a specific instance of `MyNativeView`. Now the button can control which `MyNativeView` should change its `backgroundColor`. In this example let's assume that `callNativeMethod` changes `backgroundColor`.
-```jsx title='MyNativeView.ios.js'
+```tsx title="MyNativeView.ios.tsx"
class MyNativeView extends React.Component {
callNativeMethod = () => {
UIManager.dispatchViewManagerCommand(
ReactNative.findNodeHandle(this),
UIManager.getViewManagerConfig('RNCMyNativeView').Commands
.callNativeMethod,
- []
+ [],
);
};
@@ -448,8 +448,8 @@ Here the `callNativeMethod` is defined in the `RNCMyNativeViewManager.m` file an
Since all our native react views are subclasses of `UIView`, most style attributes will work like you would expect out of the box. Some components will want a default style, however, for example `UIDatePicker` which is a fixed size. This default style is important for the layout algorithm to work as expected, but we also want to be able to override the default style when using the component. `DatePickerIOS` does this by wrapping the native component in an extra view, which has flexible styling, and using a fixed style (which is generated with constants passed in from native) on the inner native component:
-```jsx title='DatePickerIOS.ios.js'
-import { UIManager } from 'react-native';
+```tsx title="DatePickerIOS.ios.tsx"
+import {UIManager} from 'react-native';
var RCTDatePickerIOSConsts = UIManager.RCTDatePicker.Constants;
...
render: function() {
diff --git a/docs/native-modules-android.md b/docs/native-modules-android.md
index e154d587bf5..911d0a29605 100644
--- a/docs/native-modules-android.md
+++ b/docs/native-modules-android.md
@@ -109,8 +109,8 @@ override fun getName() = "CalendarModule"
The native module can then be accessed in JS like this:
-```jsx
-const { CalendarModule } = ReactNative.NativeModules;
+```tsx
+const {CalendarModule} = ReactNative.NativeModules;
```
### Export a Native Method to JavaScript
@@ -310,9 +310,9 @@ At this point, you have set up the basic scaffolding for your native module in A
Find a place in your application where you would like to add a call to the native moduleâs `createCalendarEvent()` method. Below is an example of a component, `NewModuleButton` you can add in your app. You can invoke the native module inside `NewModuleButton`'s `onPress()` function.
-```jsx
+```tsx
import React from 'react';
-import { NativeModules, Button } from 'react-native';
+import {NativeModules, Button} from 'react-native';
const NewModuleButton = () => {
const onPress = () => {
@@ -333,19 +333,19 @@ export default NewModuleButton;
In order to access your native module from JavaScript you need to first import `NativeModules` from React Native:
-```jsx
-import { NativeModules } from 'react-native';
+```tsx
+import {NativeModules} from 'react-native';
```
You can then access the `CalendarModule` native module off of `NativeModules`.
-```jsx
-const { CalendarModule } = NativeModules;
+```tsx
+const {CalendarModule} = NativeModules;
```
Now that you have the CalendarModule native module available, you can invoke your native method `createCalendarEvent()`. Below it is added to the `onPress()` method in `NewModuleButton`:
-```jsx
+```tsx
const onPress = () => {
CalendarModule.createCalendarEvent('testName', 'testLocation');
};
@@ -380,7 +380,7 @@ Importing your native module by pulling it off of `NativeModules` like above is
To save consumers of your native module from needing to do that each time they want to access your native module, you can create a JavaScript wrapper for the module. Create a new JavaScript file named `CalendarModule.js` with the following content:
-```jsx
+```tsx
/**
* This exposes the native CalendarModule module as a JS module. This has a
* function 'createCalendarEvent' which takes the following parameters:
@@ -388,32 +388,32 @@ To save consumers of your native module from needing to do that each time they w
* 1. String name: A string representing the name of the event
* 2. String location: A string representing the location of the event
*/
-import { NativeModules } from 'react-native';
-const { CalendarModule } = NativeModules;
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
export default CalendarModule;
```
This JavaScript file also becomes a good location for you to add any JavaScript side functionality. For example, if you use a type system like TypeScript you can add type annotations for your native module here. While React Native does not yet support Native to JS type safety, all your JS code will be type safe. Doing so will also make it easier for you to switch to type-safe native modules down the line. Below is an example of adding type safety to the CalendarModule:
-```jsx
+```tsx
/**
-* This exposes the native CalendarModule module as a JS module. This has a
-* function 'createCalendarEvent' which takes the following parameters:
-*
-* 1. String name: A string representing the name of the event
-* 2. String location: A string representing the location of the event
-*/
-import { NativeModules } from 'react-native';
-const { CalendarModule } = NativeModules;
+ * This exposes the native CalendarModule module as a JS module. This has a
+ * function 'createCalendarEvent' which takes the following parameters:
+ *
+ * 1. String name: A string representing the name of the event
+ * 2. String location: A string representing the location of the event
+ */
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
interface CalendarInterface {
- createCalendarEvent(name: string, location: string): void;
+ createCalendarEvent(name: string, location: string): void;
}
export default CalendarModule as CalendarInterface;
```
In your other JavaScript files you can access the native module and invoke its method like this:
-```jsx
+```tsx
import CalendarModule from './CalendarModule';
CalendarModule.createCalendarEvent('foo', 'bar');
```
@@ -503,8 +503,8 @@ override fun getConstants(): MutableMap =
The constant can then be accessed by invoking `getConstants` on the native module in JS:
-```jsx
-const { DEFAULT_EVENT_NAME } = CalendarModule.getConstants();
+```tsx
+const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
console.log(DEFAULT_EVENT_NAME);
```
@@ -570,14 +570,14 @@ You can invoke the callback in your Java/Kotlin method, providing whatever data
This method could then be accessed in JavaScript using:
-```jsx
+```tsx
const onPress = () => {
CalendarModule.createCalendarEvent(
'Party',
'My House',
- (eventId) => {
+ eventId => {
console.log(`Created a new event with id ${eventId}`);
- }
+ },
);
};
```
@@ -613,7 +613,7 @@ There are two approaches to error handling with callbacks. The first is to follo
In JavaScript, you can then check the first argument to see if an error was passed through:
-```jsx
+```tsx
const onPress = () => {
CalendarModule.createCalendarEvent(
'testName',
@@ -623,7 +623,7 @@ const onPress = () => {
console.error(`Error found! ${error}`);
}
console.log(`event id ${eventId} returned`);
- }
+ },
);
};
```
@@ -657,17 +657,17 @@ public void createCalendarEvent(String name, String location, Callback myFailure
Then in JavaScript you can add a separate callback for error and success responses:
-```jsx
+```tsx
const onPress = () => {
CalendarModule.createCalendarEvent(
'testName',
'testLocation',
- (error) => {
+ error => {
console.error(`Error found! ${error}`);
},
- (eventId) => {
+ eventId => {
console.log(`event id ${eventId} returned`);
- }
+ },
);
};
```
@@ -717,12 +717,12 @@ fun createCalendarEvent(name: String, location: String, promise: Promise) {
The JavaScript counterpart of this method returns a Promise. This means you can use the `await` keyword within an async function to call it and wait for its result:
-```jsx
+```tsx
const onSubmit = async () => {
try {
const eventId = await CalendarModule.createCalendarEvent(
'Party',
- 'My House'
+ 'My House',
);
console.log(`Created a new event with id ${eventId}`);
} catch (e) {
@@ -852,14 +852,14 @@ sendEvent(reactContext, "EventReminder", params)
JavaScript modules can then register to receive events by `addListener` on the [NativeEventEmitter](https://github.com/facebook/react-native/blob/master/Libraries/EventEmitter/NativeEventEmitter.js) class.
-```jsx
-import { NativeEventEmitter, NativeModules } from 'react-native';
+```tsx
+import {NativeEventEmitter, NativeModules} from 'react-native';
...
componentDidMount() {
...
const eventEmitter = new NativeEventEmitter(NativeModules.ToastExample);
- this.eventListener = eventEmitter.addListener('EventReminder', (event) => {
+ this.eventListener = eventEmitter.addListener('EventReminder', event => {
console.log(event.eventProperty) // "someValue"
});
...
@@ -929,7 +929,7 @@ Let's implement a basic image picker to demonstrate this. The image picker will
-```jsx
+```kotlin
public class ImagePickerModule extends ReactContextBaseJavaModule {
private static final int IMAGE_PICKER_REQUEST = 1;
@@ -1029,7 +1029,7 @@ class ImagePickerModule(reactContext: ReactApplicationContext) :
Activity.RESULT_OK -> {
val uri = intent?.data
- uri?.let { promise.resolve(uri.toString()) }
+ uri?.let { promise.resolve(uri.toString())}
?: promise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found")
}
}
diff --git a/docs/native-modules-ios.md b/docs/native-modules-ios.md
index ae590ad6cd2..b1168716133 100644
--- a/docs/native-modules-ios.md
+++ b/docs/native-modules-ios.md
@@ -75,8 +75,8 @@ RCT_EXPORT_MODULE(CalendarModuleFoo);
The native module can then be accessed in JS like this:
-```jsx
-const { CalendarModuleFoo } = ReactNative.NativeModules;
+```tsx
+const {CalendarModuleFoo} = ReactNative.NativeModules;
```
If you do not specify a name, the JavaScript module name will match the Objective-C class name, with any "RCT" or "RK" prefixes removed.
@@ -90,8 +90,8 @@ RCT_EXPORT_MODULE();
The native module can then be accessed in JS like this:
-```jsx
-const { CalendarModule } = ReactNative.NativeModules;
+```tsx
+const {CalendarModule} = ReactNative.NativeModules;
```
### Export a Native Method to JavaScript
@@ -137,9 +137,9 @@ At this point you have set up the basic scaffolding for your native module in iO
Find a place in your application where you would like to add a call to the native moduleâs `createCalendarEvent()` method. Below is an example of a component, `NewModuleButton` you can add in your app. You can invoke the native module inside `NewModuleButton`'s `onPress()` function.
-```jsx
+```tsx
import React from 'react';
-import { NativeModules, Button } from 'react-native';
+import {NativeModules, Button} from 'react-native';
const NewModuleButton = () => {
const onPress = () => {
@@ -160,19 +160,19 @@ export default NewModuleButton;
In order to access your native module from JavaScript you need to first import `NativeModules` from React Native:
-```jsx
-import { NativeModules } from 'react-native';
+```tsx
+import {NativeModules} from 'react-native';
```
You can then access the `CalendarModule` native module off of `NativeModules`.
-```jsx
-const { CalendarModule } = NativeModules;
+```tsx
+const {CalendarModule} = NativeModules;
```
Now that you have the CalendarModule native module available, you can invoke your native method `createCalendarEvent()`. Below it is added to the `onPress()` method in `NewModuleButton`:
-```jsx
+```tsx
const onPress = () => {
CalendarModule.createCalendarEvent('testName', 'testLocation');
};
@@ -207,7 +207,7 @@ Importing your native module by pulling it off of `NativeModules` like above is
To save consumers of your native module from needing to do that each time they want to access your native module, you can create a JavaScript wrapper for the module. Create a new JavaScript file named NativeCalendarModule.js with the following content:
-```jsx
+```tsx
/**
* This exposes the native CalendarModule module as a JS module. This has a
* function 'createCalendarEvent' which takes the following parameters:
@@ -215,32 +215,32 @@ To save consumers of your native module from needing to do that each time they w
* 1. String name: A string representing the name of the event
* 2. String location: A string representing the location of the event
*/
-import { NativeModules } from 'react-native';
-const { CalendarModule } = NativeModules;
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
export default CalendarModule;
```
This JavaScript file also becomes a good location for you to add any JavaScript side functionality. For example, if you use a type system like TypeScript you can add type annotations for your native module here. While React Native does not yet support Native to JS type safety, with these type annotations, all your JS code will be type safe. These annotations will also make it easier for you to switch to type-safe native modules down the line. Below is an example of adding type safety to the Calendar Module:
-```jsx
+```tsx
/**
-* This exposes the native CalendarModule module as a JS module. This has a
-* function 'createCalendarEvent' which takes the following parameters:
-*
-* 1. String name: A string representing the name of the event
-* 2. String location: A string representing the location of the event
-*/
-import { NativeModules } from 'react-native';
-const { CalendarModule } = NativeModules;
+ * This exposes the native CalendarModule module as a JS module. This has a
+ * function 'createCalendarEvent' which takes the following parameters:
+ *
+ * 1. String name: A string representing the name of the event
+ * 2. String location: A string representing the location of the event
+ */
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
interface CalendarInterface {
- createCalendarEvent(name: string, location: string): void;
+ createCalendarEvent(name: string, location: string): void;
}
export default CalendarModule as CalendarInterface;
```
In your other JavaScript files you can access the native module and invoke its method like this:
-```jsx
+```tsx
import NativeCalendarModule from './NativeCalendarModule';
NativeCalendarModule.createCalendarEvent('foo', 'bar');
```
@@ -286,8 +286,8 @@ A native module can export constants by overriding the native method `constantsT
The constant can then be accessed by invoking `getConstants()` on the native module in JS like so:
-```objectivec
-const { DEFAULT_EVENT_NAME } = CalendarModule.getConstants();
+```tsx
+const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
console.log(DEFAULT_EVENT_NAME);
```
@@ -327,14 +327,14 @@ RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title location:(NSString *)loc
This method could then be accessed in JavaScript using the following:
-```jsx
+```tsx
const onSubmit = () => {
CalendarModule.createCalendarEvent(
'Party',
'04-12-2020',
- (eventId) => {
+ eventId => {
console.log(`Created a new event with id ${eventId}`);
- }
+ },
);
};
```
@@ -353,7 +353,7 @@ RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title location:(NSStri
In JavaScript, you can then check the first argument to see if an error was passed through:
-```jsx
+```tsx
const onPress = () => {
CalendarModule.createCalendarEventCallback(
'testName',
@@ -363,7 +363,7 @@ const onPress = () => {
console.error(`Error found! ${error}`);
}
console.log(`event id ${eventId} returned`);
- }
+ },
);
};
```
@@ -389,17 +389,17 @@ RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title
Then in JavaScript you can add a separate callback for error and success responses:
-```jsx
+```tsx
const onPress = () => {
CalendarModule.createCalendarEventCallback(
'testName',
'testLocation',
- (error) => {
+ error => {
console.error(`Error found! ${error}`);
},
- (eventId) => {
+ eventId => {
console.log(`event id ${eventId} returned`);
- }
+ },
);
};
```
@@ -430,12 +430,12 @@ RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title
The JavaScript counterpart of this method returns a Promise. This means you can use the `await` keyword within an async function to call it and wait for its result:
-```jsx
+```tsx
const onSubmit = async () => {
try {
const eventId = await CalendarModule.createCalendarEvent(
'Party',
- 'my house'
+ 'my house',
);
console.log(`Created a new event with id ${eventId}`);
} catch (e) {
@@ -486,7 +486,7 @@ You will receive a warning if you expend resources unnecessarily by emitting an
- (void)calendarEventReminderReceived:(NSNotification *)notification
{
NSString *eventName = notification.userInfo[@"name"];
- if (hasListeners) { // Only send events if anyone is listening
+ if (hasListeners) {// Only send events if anyone is listening
[self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
}
}
diff --git a/docs/navigation.md b/docs/navigation.md
index e3a388eae8f..101acb85779 100644
--- a/docs/navigation.md
+++ b/docs/navigation.md
@@ -3,8 +3,6 @@ id: navigation
title: Navigating Between Screens
---
-import M1Cocoapods from './\_markdown-m1-cocoapods.mdx';
-
Mobile apps are rarely made up of a single screen. Managing the presentation of, and transition between, multiple screens is typically handled by what is known as a navigator.
This guide covers the various navigation components available in React Native. If you are getting started with navigation, you will probably want to use [React Navigation](navigation.md#react-navigation). React Navigation provides a straightforward navigation solution, with the ability to present common stack navigation and tabbed navigation patterns on both Android and iOS.
@@ -28,7 +26,7 @@ Next, install the required peer dependencies. You need to run different commands
- If you have an Expo managed project, install the dependencies with `expo`:
```shell
- expo install react-native-screens react-native-safe-area-context
+ npx expo install react-native-screens react-native-safe-area-context
```
- If you have a bare React Native project, install the dependencies with `npm`:
@@ -49,13 +47,11 @@ Next, install the required peer dependencies. You need to run different commands
You might get warnings related to peer dependencies after installation. They are usually caused by incorrect version ranges specified in some packages. You can safely ignore most warnings as long as your app builds.
:::
-
-
Now, you need to wrap the whole app in `NavigationContainer`. Usually you'd do this in your entry file, such as `index.js` or `App.js`:
-```jsx
+```tsx
import * as React from 'react';
-import { NavigationContainer } from '@react-navigation/native';
+import {NavigationContainer} from '@react-navigation/native';
const App = () => {
return (
@@ -74,10 +70,10 @@ Now you are ready to build and run your app on the device/simulator.
Now you can create an app with a home screen and a profile screen:
-```jsx
+```tsx
import * as React from 'react';
-import { NavigationContainer } from '@react-navigation/native';
-import { createNativeStackNavigator } from '@react-navigation/native-stack';
+import {NavigationContainer} from '@react-navigation/native';
+import {createNativeStackNavigator} from '@react-navigation/native-stack';
const Stack = createNativeStackNavigator();
@@ -88,7 +84,7 @@ const MyStack = () => {
@@ -103,18 +99,18 @@ You can set options such as the screen title for each screen in the `options` pr
Each screen takes a `component` prop that is a React component. Those components receive a prop called `navigation` which has various methods to link to other screens. For example, you can use `navigation.navigate` to go to the `Profile` screen:
-```jsx
-const HomeScreen = ({ navigation }) => {
+```tsx
+const HomeScreen = ({navigation}) => {
return (
- navigation.navigate('Profile', { name: 'Jane' })
+ navigation.navigate('Profile', {name: 'Jane'})
}
/>
);
};
-const ProfileScreen = ({ navigation, route }) => {
+const ProfileScreen = ({navigation, route}) => {
return This is {route.params.name}'s profile;
};
```
diff --git a/docs/network.md b/docs/network.md
index 786e4db02cc..ee4728976fa 100644
--- a/docs/network.md
+++ b/docs/network.md
@@ -15,23 +15,23 @@ React Native provides the [Fetch API](https://developer.mozilla.org/en-US/docs/W
In order to fetch content from an arbitrary URL, you can pass the URL to fetch:
-```jsx
+```tsx
fetch('https://mywebsite.com/mydata.json');
```
Fetch also takes an optional second argument that allows you to customize the HTTP request. You may want to specify additional headers, or make a POST request:
-```jsx
+```tsx
fetch('https://mywebsite.com/endpoint/', {
method: 'POST',
headers: {
Accept: 'application/json',
- 'Content-Type': 'application/json'
+ 'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
- secondParam: 'yourOtherValue'
- })
+ secondParam: 'yourOtherValue',
+ }),
});
```
@@ -43,14 +43,14 @@ The above examples show how you can make a request. In many cases, you will want
Networking is an inherently asynchronous operation. Fetch method will return a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise) that makes it straightforward to write code that works in an asynchronous manner:
-```jsx
+```tsx
const getMoviesFromApi = () => {
return fetch('https://reactnative.dev/movies.json')
- .then((response) => response.json())
- .then((json) => {
+ .then(response => response.json())
+ .then(json => {
return json.movies;
})
- .catch((error) => {
+ .catch(error => {
console.error(error);
});
};
@@ -58,11 +58,11 @@ const getMoviesFromApi = () => {
You can also use the `async` / `await` syntax in a React Native app:
-```jsx
+```tsx
const getMoviesFromApiAsync = async () => {
try {
const response = await fetch(
- 'https://reactnative.dev/movies.json'
+ 'https://reactnative.dev/movies.json',
);
const json = await response.json();
return json.movies;
@@ -77,16 +77,19 @@ Don't forget to catch any errors that may be thrown by `fetch`, otherwise they w
-```SnackPlayer name=Fetch%20Example
-import React, { useEffect, useState } from 'react';
-import { ActivityIndicator, FlatList, Text, View } from 'react-native';
+
+
-export default App = () => {
+```SnackPlayer name=Fetch%20Example&ext=js
+import React, {useEffect, useState} from 'react';
+import {ActivityIndicator, FlatList, Text, View} from 'react-native';
+
+const App = () => {
const [isLoading, setLoading] = useState(true);
const [data, setData] = useState([]);
const getMovies = async () => {
- try {
+ try {
const response = await fetch('https://reactnative.dev/movies.json');
const json = await response.json();
setData(json.movies);
@@ -95,34 +98,101 @@ export default App = () => {
} finally {
setLoading(false);
}
- }
+ };
useEffect(() => {
getMovies();
}, []);
return (
-
- {isLoading ? : (
+
+ {isLoading ? (
+
+ ) : (
id}
- renderItem={({ item }) => (
- {item.title}, {item.releaseYear}
+ keyExtractor={({id}) => id}
+ renderItem={({item}) => (
+
+ {item.title}, {item.releaseYear}
+
)}
/>
)}
);
};
+
+export default App;
```
+
+
+
+```SnackPlayer name=Fetch%20Example&ext=tsx
+import React, {useEffect, useState} from 'react';
+import {ActivityIndicator, FlatList, Text, View} from 'react-native';
+
+type Movie = {
+ id: string;
+ title: string;
+ releaseYear: string;
+};
+
+const App = () => {
+ const [isLoading, setLoading] = useState(true);
+ const [data, setData] = useState([]);
+
+ const getMovies = async () => {
+ try {
+ const response = await fetch('https://reactnative.dev/movies.json');
+ const json = await response.json();
+ setData(json.movies);
+ } catch (error) {
+ console.error(error);
+ } finally {
+ setLoading(false);
+ }
+ };
+
+ useEffect(() => {
+ getMovies();
+ }, []);
+
+ return (
+
+ {isLoading ? (
+
+ ) : (
+ id}
+ renderItem={({item}) => (
+
+ {item.title}, {item.releaseYear}
+
+ )}
+ />
+ )}
+
+ );
+};
+
+export default App;
+```
+
+
+
+
-```SnackPlayer name=Fetch%20Example
-import React, { Component } from 'react';
-import { ActivityIndicator, FlatList, Text, View } from 'react-native';
+
+
+
+```SnackPlayer name=Fetch%20Example&ext=js
+import React, {Component} from 'react';
+import {ActivityIndicator, FlatList, Text, View} from 'react-native';
export default class App extends Component {
constructor(props) {
@@ -130,7 +200,7 @@ export default class App extends Component {
this.state = {
data: [],
- isLoading: true
+ isLoading: true,
};
}
@@ -138,11 +208,11 @@ export default class App extends Component {
try {
const response = await fetch('https://reactnative.dev/movies.json');
const json = await response.json();
- this.setState({ data: json.movies });
+ this.setState({data: json.movies});
} catch (error) {
console.log(error);
} finally {
- this.setState({ isLoading: false });
+ this.setState({isLoading: false});
}
}
@@ -151,28 +221,99 @@ export default class App extends Component {
}
render() {
- const { data, isLoading } = this.state;
+ const {data, isLoading} = this.state;
return (
-
- {isLoading ? : (
+
+ {isLoading ? (
+
+ ) : (
id}
- renderItem={({ item }) => (
- {item.title}, {item.releaseYear}
+ keyExtractor={({id}) => id}
+ renderItem={({item}) => (
+
+ {item.title}, {item.releaseYear}
+
)}
/>
)}
);
}
+}
+```
+
+
+
+
+```SnackPlayer name=Fetch%20Example&ext=tsx
+import React, {Component} from 'react';
+import {ActivityIndicator, FlatList, Text, View} from 'react-native';
+
+type Movie = {
+ id: string;
+ title: string;
+ releaseYear: string;
+};
+
+type AppState = {
+ data: Movie[];
+ isLoading: boolean;
};
+
+export default class App extends Component {
+ state: AppState = {
+ data: [],
+ isLoading: true,
+ };
+
+ async getMovies() {
+ try {
+ const response = await fetch('https://reactnative.dev/movies.json');
+ const json = await response.json();
+ this.setState({data: json.movies});
+ } catch (error) {
+ console.log(error);
+ } finally {
+ this.setState({isLoading: false});
+ }
+ }
+
+ componentDidMount() {
+ this.getMovies();
+ }
+
+ render() {
+ const {data, isLoading} = this.state;
+
+ return (
+
+ {isLoading ? (
+
+ ) : (
+ id}
+ renderItem={({item}) => (
+
+ {item.title}, {item.releaseYear}
+
+ )}
+ />
+ )}
+
+ );
+ }
+}
```
+
+
+
> By default, iOS will block any request that's not encrypted using [SSL](https://hosting.review/web-hosting-glossary/#12). If you need to fetch from a cleartext URL (one that begins with `http`) you will first need to [add an App Transport Security exception](integration-with-existing-apps.md#test-your-integration). If you know ahead of time what domains you will need access to, it is more secure to add exceptions only for those domains; if the domains are not known until runtime you can [disable ATS completely](publishing-to-app-store.md#1-enable-app-transport-security). Note however that from January 2017, [Apple's App Store review will require reasonable justification for disabling ATS](https://forums.developer.apple.com/thread/48979). See [Apple's documentation](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33) for more information.
> On Android, as of API Level 28, clear text traffic is also blocked by default. This behaviour can be overridden by setting [`android:usesCleartextTraffic`](https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic) in the app manifest file.
@@ -181,9 +322,9 @@ export default class App extends Component {
The [XMLHttpRequest API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest) is built into React Native. This means that you can use third party libraries such as [frisbee](https://github.com/niftylettuce/frisbee) or [axios](https://github.com/mzabriskie/axios) that depend on it, or you can use the XMLHttpRequest API directly if you prefer.
-```jsx
+```tsx
var request = new XMLHttpRequest();
-request.onreadystatechange = (e) => {
+request.onreadystatechange = e => {
if (request.readyState !== 4) {
return;
}
@@ -205,7 +346,7 @@ request.send();
React Native also supports [WebSockets](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket), a protocol which provides full-duplex communication channels over a single TCP connection.
-```jsx
+```tsx
var ws = new WebSocket('ws://host.com/path');
ws.onopen = () => {
@@ -213,17 +354,17 @@ ws.onopen = () => {
ws.send('something'); // send a message
};
-ws.onmessage = (e) => {
+ws.onmessage = e => {
// a message was received
console.log(e.data);
};
-ws.onerror = (e) => {
+ws.onerror = e => {
// an error occurred
console.log(e.message);
};
-ws.onclose = (e) => {
+ws.onclose = e => {
// connection closed
console.log(e.code, e.reason);
};
diff --git a/docs/new-architecture-app-intro.md b/docs/new-architecture-app-intro.md
index 8fafc8ec93c..479da51b114 100644
--- a/docs/new-architecture-app-intro.md
+++ b/docs/new-architecture-app-intro.md
@@ -11,17 +11,13 @@ import constants from '@site/core/TabsConstants';
There are a few prerequisites that should be addressed before the New Architecture is enabled in your application.
-## Use a React Native >= 0.68 Release
+## Update to the latest React Native version
React Native released the support for the New Architecture with the release `0.68.0`.
-This guide is written with the expectation that youâre using the latest React Native release. At the moment of writing, this is `0.71.0`. Beside this guide, you can leverage the [upgrade helper](https://react-native-community.github.io/upgrade-helper/) to determine what other changes may be required for your project.
+This guide is written with the expectation that youâre using the [**latest** React Native release](https://github.com/facebook/react-native/releases/latest).
-To update to the most recent version of React Native, you can run this command:
-
-```bash
-npx react-native upgrade
-```
+You can find instructions on how to upgrade in the page [upgrading to new versions](/docs/upgrading).
## Use Hermes
@@ -29,7 +25,7 @@ Hermes is an open-source JavaScript engine optimized for React Native. Hermes is
We highly recommend using Hermes in your application. With Hermes enabled, you can use the JavaScript debugger in Flipper to directly debug your JavaScript code.
-Please [follow the instructions on the React Native website](hermes) to learn how to enable/disable Hermes.
+Please [follow the instructions on the Hermes page](hermes) to learn how to enable/disable Hermes.
:::caution
@@ -78,7 +74,7 @@ Turbo Native Modules can be written using Objective-C or C++. In order to suppor
## iOS - Make your AppDelegate conform to `RCTAppDelegate`
-The final step to configure iOS for the New Architecture is to extend a base class proided by React Native, called `RCTAppDelegate`.
+The final step to configure iOS for the New Architecture is to extend a base class provided by React Native, called `RCTAppDelegate`.
This class provides a base implementation for all the required functionalities of the new architecture. If you need to customize some of them, you can override those methods, invoke `[super methodNameWith:parameters:];` collecting the returned value and customize the bits you need to customize.
@@ -140,328 +136,20 @@ RCT_NEW_ARCH_ENABLED=1 pod install
## Android - Prerequisites
-Using the New Architecture on Android has some prerequisites that you need to meet:
-
-1. Using Gradle version >= 7.x
-2. Using Android Gradle Plugin >= 7.3.x (i.e. the `com.android.tools.build:gradle` dependency)
-
-If you updated to React Native 0.68+, you already meet those prerequisites. If you don't meet them, consider updating those dependencies first.
-
-## Android - React Native Gradle Plugin & Build from Source
-
-The New Architecture relies on the React Native Gradle Plugin (from the `react-native-gradle-plugin` NPM package) to build and run your project.
-
-Moreover, in this iteration of the guide you will build React Native from source.
-
-If you updated your project to React Native 0.68+, you probably already have this configuration set up correctly.
-
-If not make sure you edit the `android/settings.gradle` file as follows:
-
-```diff
- rootProject.name = 'HelloWorld'
- apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings)
- include ':app'
-+includeBuild('../node_modules/react-native-gradle-plugin')
-
-+include(":ReactAndroid")
-+project(":ReactAndroid").projectDir = file('../node_modules/react-native/ReactAndroid')
-+include(":ReactAndroid:hermes-engine")
-+project(":ReactAndroid:hermes-engine").projectDir = file('../node_modules/react-native/+ReactAndroid/hermes-engine')
-```
-
-Update the `android/build.gradle` file as follows:
-
-```diff
-buildscript {
- // ...
- dependencies {
-
- // Add those lines
-+ classpath("com.facebook.react:react-native-gradle-plugin")
-+ classpath("de.undercouch:gradle-download-task:4.1.2")
- }
-}
-```
+If you successfully updated your project to React Native `0.71.0`, you **already meet** all the prerequisites to use the New Architecture on Android.
-And update the `android/app/build.gradle` file (please note that this file is different than the top level `build.gradle`) as follows:
+You will only need to update your `android/gradle.properties` file as follows:
```diff
-dependencies {
- // ...
- if (enableHermes) {
-- def hermesPath = "../../node_modules/hermes-engine/android/";
-- debugImplementation files(hermesPath + "hermes-debug.aar")
-- releaseImplementation files(hermesPath + "hermes-release.aar")
-+ //noinspection GradleDynamicVersion
-+ implementation("com.facebook.react:hermes-engine:+") // From node_modules
- }
-}
-
-+ configurations.all {
-+ resolutionStrategy.dependencySubstitution {
-+ substitute(module("com.facebook.react:react-native"))
-+ .using(project(":ReactAndroid"))
-+ .because("On New Architecture we're building React Native from source")
-+ substitute(module("com.facebook.react:hermes-engine"))
-+ .using(project(":ReactAndroid:hermes-engine"))
-+ .because("On New Architecture we're building Hermes from source")
-+ }
-+ }
-```
-
-## Android - Configure the NDK
-
-:::caution
-
-In this iteration of the guide youâre setting up the project to build from source. You might notice an increase in your build time because of this.
-You can mitigate this by following the approach described in [Speeding up your Build phase](/docs/next/build-speed) guide.
-
-:::
-
-As Codegen will output some Java and some C++ code that needs to build, you need to configure the Android NDK to do so.
-
-Edit your `android/app/build.gradle` file to include the **two** `externalNativeBuild` blocks detailed below inside the `android{}` block:
-
-```groovy
-android {
- defaultConfig {
- applicationId "com.awesomeproject"
- // ...
-
- // Add this block
- externalNativeBuild {
- cmake {
- arguments "-DPROJECT_BUILD_DIR=$buildDir",
- "-DREACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
- "-DREACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
- "-DANDROID_STL=c++_shared"
- }
- }
- }
-
- // Add this block
- externalNativeBuild {
- cmake {
- path "$projectDir/src/main/jni/CMakeLists.txt"
- }
- }
-}
-```
-
-Finally, you need to create two files that are required to build the native code correctly:
-
-- A CMake file with the compilation instructions (similar to a `build.gradle` for Android/Java)
-- An `OnLoad.cpp` file which, as the name says, will be loaded when your app starts.
-
-Create a file inside the `android/app/src/main/jni` folder called `CMakeLists.txt` with the following content:
-
-```cmake title="CMakeLists.txt"
-cmake_minimum_required(VERSION 3.13)
-
-# Define the library name here.
-project(appmodules)
-
-# This file includes all the necessary to let you build your application with the New Architecture.
-include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)
+# Use this property to enable support to the new architecture.
+# This will allow you to use TurboModules and the Fabric render in
+# your application. You should enable this flag either if you want
+# to write custom TurboModules/Fabric components OR use libraries that
+# are providing them.
+-newArchEnabled=false
++newArchEnabled=true
```
-And create the `android/app/src/main/jni/OnLoad.cpp` file with the following content:
-
-```cpp title="OnLoad.cpp"
-#include
-#include
-#include
-#include
-#include
-
-namespace facebook {
-namespace react {
-
-void registerComponents(
- std::shared_ptr registry) {
- // Custom Fabric Components go here. You can register custom
- // components coming from your App or from 3rd party libraries here.
- //
- // providerRegistry->add(concreteComponentDescriptorProvider<
- // AocViewerComponentDescriptor>());
-
- // By default we just use the components autolinked by RN CLI
- rncli_registerProviders(registry);
-}
-
-std::shared_ptr provideModules(
- const std::string &name,
- const JavaTurboModule::InitParams ¶ms) {
- // Here you can provide your own module provider for TurboModules coming from
- // either your application or from external libraries. The approach to follow
- // is similar to the following (for a library called `samplelibrary`):
- //
- // auto module = samplelibrary_ModuleProvider(moduleName, params);
- // if (module != nullptr) {
- // return module;
- // }
- // return rncore_ModuleProvider(moduleName, params);
-
- // By default we just use the module providers autolinked by RN CLI
- return rncli_ModuleProvider(name, params);
-}
-
-} // namespace react
-} // namespace facebook
-
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
- return facebook::jni::initialize(vm, [] {
- facebook::react::DefaultTurboModuleManagerDelegate::
- moduleProvidersFromEntryPoint = &facebook::react::provideModules;
- facebook::react::DefaultComponentsRegistry::
- registerComponentDescriptorsFromEntryPoint =
- &facebook::react::registerComponents;
- });
-}
-```
-
-When the app loads, this file will take care of registering the Native Components and Modules which provide native sources. By default we only provide the autolinked libraries as this allows you to use those libraries.
-
-This is the only C++ file you'll have to add to your project, and the infrastructure will take care of the rest.
-
-## Android - Update your Java classes
-
-To simplify how to enable the New Architecture on Android, you can use some utility classes that will take care of all the setup without you having to worry about it.
-
-Those classes are all located inside the `com.facebook.react.defaults` package and are all named `Defaults*`.
-
-### Update the React Native Host
-
-First, update your `ReactNativeHost` as follows (usually located in your `MainApplication.java` file):
-
-
-
-
-```diff title="MainApplication.java"
-+import com.facebook.react.defaults.DefaultReactNativeHost;
-
- private final ReactNativeHost mReactNativeHost =
-- new ReactNativeHost(this) {
-+ new DefaultReactNativeHost(this) {
-
- @Override
- public boolean getUseDeveloperSupport() {
- return BuildConfig.DEBUG;
- }
-
-+ @Override
-+ public boolean isNewArchEnabled() {
-+ return true;
-+ }
-```
-
-
-
-
-```diff title="MainApplication.kt"
-+import com.facebook.react.defaults.DefaultReactNativeHost
-
- val reactNativeHost =
-- ReactNativeHost(this) {
-+ DefaultReactNativeHost(this) {
-
- override fun getUseDeveloperSupport() = BuildConfig.DEBUG
-+ override fun isNewArchEnabled() = true
-
- }
-```
-
-
-
-
-### Update the your application OnCreate
-
-Still inside your `MainApplication` method `onCreate`, make sure that the New Architecture infrastructure is loaded correctly:
-
-
-
-
-```diff title="MainApplication.java"
-+import com.facebook.react.defaults.DefaultNativeEntryPoint;
-
- @Override
- public void onCreate() {
- super.onCreate();
- SoLoader.init(this, /* native exopackage */ false);
- // Make sure it's called after SoLoader.init
-+ ReactFeatureFlags.useTurboModules = true;
-+ DefaultNativeEntryPoint.load();
- ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
- }
-```
-
-
-
-
-```diff title="MainApplication.kt"
-+import com.facebook.react.defaults.DefaultNativeEntryPoint
-
- override fun onCreate() {
- super.onCreate()
- SoLoader.init(this, /* native exopackage */ false)
- // Make sure it's called after SoLoader.init
-+ ReactFeatureFlags.useTurboModules = true
-+ DefaultNativeEntryPoint.load()
- ReactNativeFlipper.initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
- }
-```
-
-
-
-
-### Update your Activity Delegate
-
-Finally, update your `MainActivity.java` file by providing a React Activity Delegate:
-
-
-
-
-```diff title="MainActivity.java"
-+import com.facebook.react.defaults.DefaultReactActivityDelegate;
-
-public class MainActivity extends ReactActivity {
-
-+ @Override
-+ protected ReactActivityDelegate createReactActivityDelegate() {
-+ return new DefaultReactActivityDelegate(
-+ this,
-+ getMainComponentName(),
-+ true, // Here we enable Fabric
-+ true, // Here we enable Concurrent React Features
-+ );
-+ }
-
-}
-```
-
-
-
-
-```diff title="MainApplication.kt"
-+import com.facebook.react.defaults.DefaultReactActivityDelegate;
-
-public class MainActivity : ReactActivity {
-
-+ @Override
-+ override protected fun createReactActivityDelegate() =
-+ DefaultReactActivityDelegate(
-+ this,
-+ mainComponentName,
-+ true, // Here we enable Fabric
-+ true, // Here we enable Concurrent React Features
-+ )
-
-}
-```
-
-
-
-
That's it!
Itâs now time to run your Android app to verify that everything works correctly:
diff --git a/docs/new-architecture-library-intro.md b/docs/new-architecture-library-intro.md
index 4f0a3750dd5..3652849723b 100644
--- a/docs/new-architecture-library-intro.md
+++ b/docs/new-architecture-library-intro.md
@@ -54,8 +54,8 @@ export default (TurboModuleRegistry.get(''): ?Spec);
```ts
-import type { TurboModule } from 'react-native';
-import { TurboModuleRegistry } from 'react-native';
+import type {TurboModule} from 'react-native';
+import {TurboModuleRegistry} from 'react-native';
export interface Spec extends TurboModule {
readonly getConstants: () => {};
@@ -102,8 +102,8 @@ export default (codegenNativeComponent(
```ts
-import type { ViewProps } from 'ViewPropTypes';
-import type { HostComponent } from 'react-native';
+import type {ViewProps} from 'ViewPropTypes';
+import type {HostComponent} from 'react-native';
import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
export interface NativeProps extends ViewProps {
@@ -111,7 +111,7 @@ export interface NativeProps extends ViewProps {
}
export default codegenNativeComponent(
- ''
+ '',
) as HostComponent;
```
@@ -156,7 +156,7 @@ If your existing native module has methods with the same name on multiple platfo
### Android
-On Android, this generally requires you to include `native_modules.gradle` in both your `settings.gradle[.kts]` and `build.gradle[.kts]`.
+On Android, this generally requires you to include `native_modules.gradle` in both your `settings.gradle` and `build.gradle`.
If you used the default template provided with React Native (i.e., `yarn react-native init `), then autolinking is already enabled.
@@ -241,15 +241,15 @@ Most of the migration work requires a HostComponent ref to access certain APIs t
As a concrete example, this code uses `findNodeHandle` to tunnel from `ParentComponent` through to the `View` rendered by `ChildComponent`.
-```jsx
+```tsx
class ParentComponent extends React.Component {
- _ref: ?React.ElementRef;
+ _ref?: React.ElementRef;
render() {
return
}
- _captureRef: (ref) => {
+ _captureRef: (ref: React.ElementRef) => {
this._ref = ref;
}
@@ -279,15 +279,15 @@ We canât convert this call to `this._ref.measure` because `this._ref` is an in
#### Using `forwardRef`
-```jsx
+```tsx
class ParentComponent extends React.Component {
- _ref: ?React.ElementRef;
+ _ref?: React.ElementRef;
render() {
return
}
- _captureRef: (ref) => {
+ _captureRef: (ref: React.ElementRef) => {
this._ref = ref;
}
@@ -311,13 +311,13 @@ const ChildComponent = React.forwardRef((props, forwardedRef) => {
```tsx
class ParentComponent extends React.Component {
- _ref: ?React.ElementRef;
+ _ref?: React.ElementRef;
render() {
return
}
- _captureRef: (ref) => {
+ _captureRef: (ref: React.ElementRef) => {
this._ref = ref;
}
@@ -329,7 +329,7 @@ class ParentComponent extends React.Component {
}
class ChildComponent extends React.Component {
- _ref: ?React.ElementRef;
+ _ref?: React.ElementRef;
render() {
return (
@@ -343,7 +343,7 @@ class ChildComponent extends React.Component {
return this._ref;
}
- _captureRef: (ref) => {
+ _captureRef: (ref: React.ElementRef) => {
this._ref = ref;
}
}
@@ -393,7 +393,7 @@ class MyComponent extends React.Component {
style={styles.view} />
}
- _captureRef: (ref) => {
+ _captureRef: (ref: React.ElementRef) => {
this._viewRef = ref;
}
@@ -407,7 +407,7 @@ class MyComponent extends React.Component {
}
const styles = StyleSheet.create({
- view: { backgroundColor: 'white'},
+ view: {backgroundColor: 'white'},
submittedView: {borderWidth: 1}
});
```
@@ -419,7 +419,7 @@ In this example, when the View is pressed, there is a `setNativeProps` call to u
On the first render, the component props are those declared in the render function. After the View is pressed `_onSubmit` calls `setNativeProps` with updated prop values.
The resulting component can be represented as such:
-```jsx
+```tsx
```
@@ -459,14 +459,14 @@ class MyComponent extends React.Component {
}
_onSubmit: () => {
- this.setState(state => ({ ...state, hasSubmitted: true }));
+ this.setState(state => ({...state, hasSubmitted: true}));
// ...other logic for onSubmit
}
}
const styles = StyleSheet.create({
- view: { backgroundColor: 'white'},
+ view: {backgroundColor: 'white'},
submittedView: {borderWidth: 1}
});
```
@@ -492,7 +492,7 @@ return ;
#### New way
-```js title="RNTMyNativeNativeComponent.js"
+```tsx title="RNTMyNativeNativeComponent.tsx"
import RNTMyNativeViewNativeComponent from './RNTMyNativeViewNativeComponent';
[...]
@@ -500,11 +500,11 @@ import RNTMyNativeViewNativeComponent from './RNTMyNativeViewNativeComponent';
return ;
```
-```js title="RNTMyNativeViewNativeComponent.js"
-import { requireNativeComponent } from 'react-native';
+```tsx title="RNTMyNativeViewNativeComponent.tsx"
+import {requireNativeComponent} from 'react-native';
const RNTMyNativeViewNativeComponent = requireNativeComponent(
- 'RNTMyNativeView'
+ 'RNTMyNativeView',
);
export default RNTMyNativeViewNativeComponent;
@@ -515,7 +515,7 @@ export default RNTMyNativeViewNativeComponent;
If `requireNativeComponent` is not typed, you can temporarily use the `mixed` type to fix the Flow warning, for example:
```js
-import type { HostComponent } from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
+import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
// ...
const RCTWebViewNativeComponent: HostComponent =
requireNativeComponent < mixed > 'RNTMyNativeView';
@@ -525,7 +525,7 @@ const RCTWebViewNativeComponent: HostComponent =
When you are ready to migrate to Fabric you can replace `requireNativeComponent` with `codegenNativeComponent`:
-```ts title="RNTMyNativeViewNativeComponent.js"
+```ts title="RNTMyNativeViewNativeComponent.ts"
export default (codegenNativeComponent(
'RNTMyNativeView',
): HostComponent);
@@ -533,7 +533,7 @@ export default (codegenNativeComponent(
And update the main file:
-```ts title="RNTMyNativeNativeComponent.js"
+```ts title="RNTMyNativeNativeComponent.ts"
export default require('./RNTMyNativeViewNativeComponent')
.default;
```
@@ -562,9 +562,9 @@ class MyComponent extends React.Component {
**Creating NativeCommands with `codegenNativeCommands`**
-```ts title="MyCustomMapNativeComponent.js"
+```ts title="MyCustomMapNativeComponent.ts"
import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
-import type { HostComponent } from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
+import type {HostComponent} from 'react-native/Libraries/Renderer/shims/ReactNativeTypes';
type MyCustomMapNativeComponentType = HostComponent;
@@ -591,12 +591,12 @@ Note:
#### Using Your Command
```tsx
-import {Commands, ... } from './MyCustomMapNativeComponent';
+import {Commands, ...} from './MyCustomMapNativeComponent';
class MyComponent extends React.Component {
- _ref: ?React.ElementRef;
+ _ref?: React.ElementRef;
- _captureRef: (ref) => {
+ _captureRef: (ref: React.ElementRef) => {
this._ref = ref;
}
diff --git a/docs/new-architecture-library-ios.md b/docs/new-architecture-library-ios.md
index aaad8085baa..f508e690870 100644
--- a/docs/new-architecture-library-ios.md
+++ b/docs/new-architecture-library-ios.md
@@ -3,7 +3,6 @@ id: new-architecture-library-ios
title: Enabling in iOS Library
---
-import M1Cocoapods from './\_markdown-m1-cocoapods.mdx';
import NewArchitectureWarning from './\_markdown-new-architecture-warning.mdx';
diff --git a/docs/new-architecture-troubleshooting.md b/docs/new-architecture-troubleshooting.md
index 09bd0e6dc93..78eb1aea78e 100644
--- a/docs/new-architecture-troubleshooting.md
+++ b/docs/new-architecture-troubleshooting.md
@@ -57,7 +57,6 @@ Make sure to uncomment the line and set the preferred memory size with the `-Xmx
## Android NDK and Mac with M1 Apple Silicon CPUs
We're aware of a series of incompatibilities between the Android NDK and Macs on M1 CPUs ([here](https://github.com/android/ndk/issues/1299) and [here](https://github.com/android/ndk/issues/1410)).
-As you need to enable the NDK when building from source, you might face problems during your build.
+As the New Architectecture relies on the NDK, you might face problems during your build.
-The workaround at this stage is [suggested here](https://github.com/android/ndk/issues/1299).
-As newer version of the Android SDK/NDK are released, we will update the documentation with the necessary steps.
+React Native version 0.70 and 0.71 contains fixes for those build failures, and we invite you to update to those versions whenever possible.
diff --git a/docs/optimizing-flatlist-configuration.md b/docs/optimizing-flatlist-configuration.md
index 716d4d6c447..e2bcedd0e1d 100644
--- a/docs/optimizing-flatlist-configuration.md
+++ b/docs/optimizing-flatlist-configuration.md
@@ -99,7 +99,7 @@ The heavier your components are, the slower they render. Avoid heavy images (use
Implement update verification to your components. React's `PureComponent` implement a [`shouldComponentUpdate`](https://reactjs.org/docs/react-component.html#shouldcomponentupdate) with shallow comparison. This is expensive here because it needs to check all your props. If you want a good bit-level performance, create the strictest rules for your list item components, checking only props that could potentially change. If your list is basic enough, you could even use
-```jsx
+```tsx
shouldComponentUpdate() {
return false
}
@@ -128,8 +128,8 @@ Move out the `renderItem` function to the outside of render function, so it won'
-```jsx
-renderItem = ({ item }) => ({item.title});
+```tsx
+renderItem = ({item}) => ({item.title});
render(){
// ...
@@ -147,12 +147,12 @@ render(){
-```jsx
-const renderItem = ({ item }) => (
+```tsx
+const renderItem = useCallback(({item}) => (
{item.title}
- );
+ ), []);
return (
// ...
diff --git a/docs/panresponder.md b/docs/panresponder.md
index 220a5de64fe..35bea487869 100644
--- a/docs/panresponder.md
+++ b/docs/panresponder.md
@@ -32,7 +32,7 @@ A `gestureState` object has the following:
## Usage Pattern
-```jsx
+```tsx
const ExampleComponent = () => {
const panResponder = React.useRef(
PanResponder.create({
@@ -68,8 +68,8 @@ const ExampleComponent = () => {
// Returns whether this component should block native components from becoming the JS
// responder. Returns true by default. Is currently only supported on android.
return true;
- }
- })
+ },
+ }),
).current;
return ;
@@ -84,8 +84,8 @@ const ExampleComponent = () => {
```SnackPlayer name=PanResponder
-import React, { useRef } from "react";
-import { Animated, View, StyleSheet, PanResponder, Text } from "react-native";
+import React, {useRef} from 'react';
+import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native';
const App = () => {
const pan = useRef(new Animated.ValueXY()).current;
@@ -93,22 +93,11 @@ const App = () => {
const panResponder = useRef(
PanResponder.create({
onMoveShouldSetPanResponder: () => true,
- onPanResponderGrant: () => {
- pan.setOffset({
- x: pan.x._value,
- y: pan.y._value
- });
- },
- onPanResponderMove: Animated.event(
- [
- null,
- { dx: pan.x, dy: pan.y }
- ]
- ),
+ onPanResponderMove: Animated.event([null, {dx: pan.x, dy: pan.y}]),
onPanResponderRelease: () => {
- pan.flattenOffset();
- }
- })
+ pan.extractOffset();
+ },
+ }),
).current;
return (
@@ -116,33 +105,32 @@ const App = () => {
Drag this box!
+ {...panResponder.panHandlers}>
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
titleText: {
fontSize: 14,
lineHeight: 24,
- fontWeight: "bold"
+ fontWeight: 'bold',
},
box: {
height: 150,
width: 150,
- backgroundColor: "blue",
- borderRadius: 5
- }
+ backgroundColor: 'blue',
+ borderRadius: 5,
+ },
});
export default App;
@@ -152,26 +140,20 @@ export default App;
```SnackPlayer name=PanResponder
-import React, { Component } from "react";
-import { Animated, View, StyleSheet, PanResponder, Text } from "react-native";
+import React, {Component} from 'react';
+import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native';
class App extends Component {
pan = new Animated.ValueXY();
panResponder = PanResponder.create({
onMoveShouldSetPanResponder: () => true,
- onPanResponderGrant: () => {
- this.pan.setOffset({
- x: this.pan.x._value,
- y: this.pan.y._value
- });
- },
onPanResponderMove: Animated.event([
null,
- { dx: this.pan.x, dy: this.pan.y }
+ {dx: this.pan.x, dy: this.pan.y},
]),
onPanResponderRelease: () => {
- this.pan.flattenOffset();
- }
+ this.pan.extractOffset();
+ },
});
render() {
@@ -180,10 +162,9 @@ class App extends Component {
Drag this box!
+ {...this.panResponder.panHandlers}>
@@ -194,20 +175,20 @@ class App extends Component {
const styles = StyleSheet.create({
container: {
flex: 1,
- alignItems: "center",
- justifyContent: "center"
+ alignItems: 'center',
+ justifyContent: 'center',
},
titleText: {
fontSize: 14,
lineHeight: 24,
- fontWeight: "bold"
+ fontWeight: 'bold',
},
box: {
height: 150,
width: 150,
- backgroundColor: "blue",
- borderRadius: 5
- }
+ backgroundColor: 'blue',
+ borderRadius: 5,
+ },
});
export default App;
@@ -226,8 +207,8 @@ Try the [PanResponder example in RNTester](https://github.com/facebook/react-nat
### `create()`
-```jsx
-static create(config)
+```tsx
+static create(config: PanResponderCallbacks): PanResponderInstance;
```
**Parameters:**
diff --git a/docs/performance.md b/docs/performance.md
index 6076a3b0a31..dcfe3dcee36 100644
--- a/docs/performance.md
+++ b/docs/performance.md
@@ -91,7 +91,7 @@ On iOS, each time you adjust the width or height of an Image component it is re-
Sometimes, if we do an action in the same frame that we are adjusting the opacity or highlight of a component that is responding to a touch, we won't see that effect until after the `onPress` function has returned. If `onPress` does a `setState` that results in a lot of work and a few frames dropped, this may occur. A solution to this is to wrap any action inside of your `onPress` handler in `requestAnimationFrame`:
-```jsx
+```tsx
handleOnPress() {
requestAnimationFrame(() => {
this.doExpensiveAction();
diff --git a/docs/permissionsandroid.md b/docs/permissionsandroid.md
index b032e38dce7..b24af29bf0f 100644
--- a/docs/permissionsandroid.md
+++ b/docs/permissionsandroid.md
@@ -24,27 +24,34 @@ If a user has previously turned off a permission that you prompt for, the OS wil
```SnackPlayer name=PermissionsAndroid%20Example&supportedPlatforms=android
-import React from "react";
-import { Button, PermissionsAndroid, SafeAreaView, StatusBar, StyleSheet, Text, View } from "react-native";
+import React from 'react';
+import {
+ Button,
+ PermissionsAndroid,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
const requestCameraPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
- title: "Cool Photo App Camera Permission",
+ title: 'Cool Photo App Camera Permission',
message:
- "Cool Photo App needs access to your camera " +
- "so you can take awesome pictures.",
- buttonNeutral: "Ask Me Later",
- buttonNegative: "Cancel",
- buttonPositive: "OK"
- }
+ 'Cool Photo App needs access to your camera ' +
+ 'so you can take awesome pictures.',
+ buttonNeutral: 'Ask Me Later',
+ buttonNegative: 'Cancel',
+ buttonPositive: 'OK',
+ },
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
- console.log("You can use the camera");
+ console.log('You can use the camera');
} else {
- console.log("Camera permission denied");
+ console.log('Camera permission denied');
}
} catch (err) {
console.warn(err);
@@ -61,17 +68,17 @@ const App = () => (
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center",
+ justifyContent: 'center',
paddingTop: StatusBar.currentHeight,
- backgroundColor: "#ecf0f1",
- padding: 8
+ backgroundColor: '#ecf0f1',
+ padding: 8,
},
item: {
margin: 24,
fontSize: 18,
- fontWeight: "bold",
- textAlign: "center"
- }
+ fontWeight: 'bold',
+ textAlign: 'center',
+ },
});
export default App;
@@ -81,27 +88,34 @@ export default App;
```SnackPlayer name=PermissionsAndroid%20Example&supportedPlatforms=android
-import React, { Component } from "react";
-import { Button, PermissionsAndroid, SafeAreaView, StatusBar, StyleSheet, Text, View } from "react-native";
+import React, {Component} from 'react';
+import {
+ Button,
+ PermissionsAndroid,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
const requestCameraPermission = async () => {
try {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.CAMERA,
{
- title: "Cool Photo App Camera Permission",
+ title: 'Cool Photo App Camera Permission',
message:
- "Cool Photo App needs access to your camera " +
- "so you can take awesome pictures.",
- buttonNeutral: "Ask Me Later",
- buttonNegative: "Cancel",
- buttonPositive: "OK"
- }
+ 'Cool Photo App needs access to your camera ' +
+ 'so you can take awesome pictures.',
+ buttonNeutral: 'Ask Me Later',
+ buttonNegative: 'Cancel',
+ buttonPositive: 'OK',
+ },
);
if (granted === PermissionsAndroid.RESULTS.GRANTED) {
- console.log("You can use the camera");
+ console.log('You can use the camera');
} else {
- console.log("Camera permission denied");
+ console.log('Camera permission denied');
}
} catch (err) {
console.warn(err);
@@ -117,22 +131,22 @@ class App extends Component {
);
}
-};
+}
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center",
+ justifyContent: 'center',
paddingTop: StatusBar.currentHeight,
- backgroundColor: "#ecf0f1",
- padding: 8
+ backgroundColor: '#ecf0f1',
+ padding: 8,
},
item: {
margin: 24,
fontSize: 18,
- fontWeight: "bold",
- textAlign: "center"
- }
+ fontWeight: 'bold',
+ textAlign: 'center',
+ },
});
export default App;
@@ -183,7 +197,7 @@ Available as constants under `PermissionsAndroid.PERMISSIONS`:
- `READ_MEDIA_IMAGES`: 'android.permission.READ_MEDIA_IMAGES'
- `READ_MEDIA_VIDEO`: 'android.permission.READ_MEDIA_VIDEO'
- `READ_MEDIA_AUDIO`: 'android.permission.READ_MEDIA_AUDIO'
-- `POST_NOTIFICATION`: 'android.permission.POST_NOTIFICATIONS'
+- `POST_NOTIFICATIONS`: 'android.permission.POST_NOTIFICATIONS'
- `NEARBY_WIFI_DEVICES`: 'android.permission.NEARBY_WIFI_DEVICES'
- `READ_VOICEMAIL`: 'com.android.voicemail.permission.READ_VOICEMAIL',
- `WRITE_VOICEMAIL`: 'com.android.voicemail.permission.WRITE_VOICEMAIL',
@@ -202,18 +216,10 @@ Available as constants under `PermissionsAndroid.RESULTS`:
## Methods
-### `constructor()`
-
-```jsx
-constructor();
-```
-
----
-
### `check()`
-```jsx
-check(permission);
+```tsx
+static check(permission: Permission): Promise;
```
Returns a promise resolving to a boolean value as to whether the specified permissions has been granted.
@@ -228,8 +234,11 @@ Returns a promise resolving to a boolean value as to whether the specified permi
### `request()`
-```jsx
-request(permission, [rationale]);
+```tsx
+static request(
+ permission: Permission,
+ rationale?: Rationale,
+): Promise;
```
Prompts the user to enable a permission and returns a promise resolving to a string value (see result strings above) indicating whether the user allowed or denied the request or does not want to be asked again.
@@ -257,8 +266,10 @@ If `rationale` is provided, this function checks with the OS whether it is neces
### `requestMultiple()`
-```jsx
-requestMultiple(permissions);
+```tsx
+static requestMultiple(
+ permissions: Permission[],
+): Promise<{[key in Permission]: PermissionStatus}>;
```
Prompts the user to enable multiple permissions in the same dialog and returns an object with the permissions as keys and strings as values (see result strings above) indicating whether the user allowed or denied the request or does not want to be asked again.
diff --git a/docs/pixelratio.md b/docs/pixelratio.md
index 6b397bf52fc..6215d7bf501 100644
--- a/docs/pixelratio.md
+++ b/docs/pixelratio.md
@@ -9,12 +9,12 @@ title: PixelRatio
You should get a higher resolution image if you are on a high pixel density device. A good rule of thumb is to multiply the size of the image you display by the pixel ratio.
-```jsx
-var image = getImage({
+```tsx
+const image = getImage({
width: PixelRatio.getPixelSizeForLayoutSize(200),
- height: PixelRatio.getPixelSizeForLayoutSize(100)
+ height: PixelRatio.getPixelSizeForLayoutSize(100),
});
-;
+;
```
## Pixel grid snapping
@@ -30,14 +30,21 @@ In React Native, everything in JavaScript and within the layout engine works wit
## Example
```SnackPlayer name=PixelRatio%20Example
-import React from "react";
-import { Image, PixelRatio, ScrollView, StyleSheet, Text, View } from "react-native";
+import React from 'react';
+import {
+ Image,
+ PixelRatio,
+ ScrollView,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
const size = 50;
const cat = {
- uri: "https://reactnative.dev/docs/assets/p_cat1.png",
+ uri: 'https://reactnative.dev/docs/assets/p_cat1.png',
width: size,
- height: size
+ height: size,
};
const App = () => (
@@ -64,7 +71,7 @@ const App = () => (
source={cat}
style={{
width: PixelRatio.getPixelSizeForLayoutSize(size),
- height: PixelRatio.getPixelSizeForLayoutSize(size)
+ height: PixelRatio.getPixelSizeForLayoutSize(size),
}}
/>
@@ -76,14 +83,14 @@ const styles = StyleSheet.create({
flex: 1,
},
container: {
- justifyContent: "center",
- alignItems: "center"
+ justifyContent: 'center',
+ alignItems: 'center',
},
value: {
fontSize: 24,
marginBottom: 12,
- marginTop: 4
- }
+ marginTop: 4,
+ },
});
export default App;
@@ -97,8 +104,8 @@ export default App;
### `get()`
-```jsx
-static get()
+```tsx
+static get(): number;
```
Returns the device pixel density. Some examples:
@@ -127,8 +134,8 @@ Returns the device pixel density. Some examples:
### `getFontScale()`
-```jsx
-static getFontScale(): number
+```tsx
+static getFontScale(): number;
```
Returns the scaling factor for font sizes. This is the ratio that is used to calculate the absolute font size, so any elements that heavily depend on that should use this to do calculations.
@@ -142,8 +149,8 @@ If a font scale is not set, this returns the device pixel ratio.
### `getPixelSizeForLayoutSize()`
-```jsx
-static getPixelSizeForLayoutSize(layoutSize: number): number
+```tsx
+static getPixelSizeForLayoutSize(layoutSize: number): number;
```
Converts a layout size (dp) to pixel size (px).
@@ -154,8 +161,8 @@ Guaranteed to return an integer number.
### `roundToNearestPixel()`
-```jsx
-static roundToNearestPixel(layoutSize: number): number
+```tsx
+static roundToNearestPixel(layoutSize: number): number;
```
Rounds a layout size (dp) to the nearest layout size that corresponds to an integer number of pixels. For example, on a device with a PixelRatio of 3, `PixelRatio.roundToNearestPixel(8.4) = 8.33`, which corresponds to exactly (8.33 \* 3) = 25 pixels.
diff --git a/docs/platform-specific-code.md b/docs/platform-specific-code.md
index dc177fd9103..d82b573a295 100644
--- a/docs/platform-specific-code.md
+++ b/docs/platform-specific-code.md
@@ -16,11 +16,11 @@ Certain components may have properties that work on one platform only. All of th
React Native provides a module that detects the platform in which the app is running. You can use the detection logic to implement platform-specific code. Use this option when only small parts of a component are platform-specific.
-```jsx
-import { Platform, StyleSheet } from 'react-native';
+```tsx
+import {Platform, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
- height: Platform.OS === 'ios' ? 200 : 100
+ height: Platform.OS === 'ios' ? 200 : 100,
});
```
@@ -28,25 +28,25 @@ const styles = StyleSheet.create({
There is also a `Platform.select` method available, that given an object where keys can be one of `'ios' | 'android' | 'native' | 'default'`, returns the most fitting value for the platform you are currently running on. That is, if you're running on a phone, `ios` and `android` keys will take preference. If those are not specified, `native` key will be used and then the `default` key.
-```jsx
-import { Platform, StyleSheet } from 'react-native';
+```tsx
+import {Platform, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
...Platform.select({
ios: {
- backgroundColor: 'red'
+ backgroundColor: 'red',
},
android: {
- backgroundColor: 'green'
+ backgroundColor: 'green',
},
default: {
// other platforms, web for example
- backgroundColor: 'blue'
- }
- })
- }
+ backgroundColor: 'blue',
+ },
+ }),
+ },
});
```
@@ -54,19 +54,19 @@ This will result in a container having `flex: 1` on all platforms, a red backgro
Since it accepts `any` value, you can also use it to return platform-specific components, like below:
-```jsx
+```tsx
const Component = Platform.select({
ios: () => require('ComponentIOS'),
- android: () => require('ComponentAndroid')
+ android: () => require('ComponentAndroid'),
})();
;
```
-```jsx
+```tsx
const Component = Platform.select({
native: () => require('ComponentForNative'),
- default: () => require('ComponentForWeb')
+ default: () => require('ComponentForWeb'),
})();
;
@@ -76,8 +76,8 @@ const Component = Platform.select({
On Android, the `Platform` module can also be used to detect the version of the Android Platform in which the app is running:
-```jsx
-import { Platform } from 'react-native';
+```tsx
+import {Platform} from 'react-native';
if (Platform.Version === 25) {
console.log('Running on Nougat!');
@@ -90,8 +90,8 @@ if (Platform.Version === 25) {
On iOS, the `Version` is a result of `-[UIDevice systemVersion]`, which is a string with the current version of the operating system. An example of the system version is "10.3". For example, to detect the major version number on iOS:
-```jsx
-import { Platform } from 'react-native';
+```tsx
+import {Platform} from 'react-native';
const majorVersionIOS = parseInt(Platform.Version, 10);
if (majorVersionIOS <= 9) {
@@ -110,9 +110,9 @@ BigButton.ios.js
BigButton.android.js
```
-You can then require the component as follows:
+You can then import the component as follows:
-```jsx
+```tsx
import BigButton from './BigButton';
```
@@ -129,9 +129,9 @@ Container.js # picked up by Webpack, Rollup or any other Web bundler
Container.native.js # picked up by the React Native bundler for both Android and iOS (Metro)
```
-You can still require it without the `.native` extension, as follows:
+You can still import it without the `.native` extension, as follows:
-```jsx
+```tsx
import Container from './Container';
```
diff --git a/docs/platform.md b/docs/platform.md
index 2afa34593de..5525d43401d 100644
--- a/docs/platform.md
+++ b/docs/platform.md
@@ -7,7 +7,7 @@ title: Platform
```SnackPlayer name=Platform%20API%20Example&supportedPlatforms=ios,android
import React from 'react';
-import { Platform, StyleSheet, Text, ScrollView } from 'react-native';
+import {Platform, StyleSheet, Text, ScrollView} from 'react-native';
const App = () => {
return (
@@ -18,10 +18,12 @@ const App = () => {
{Platform.Version}isTV{Platform.isTV.toString()}
- {Platform.OS === 'ios' && <>
- isPad
- {Platform.isPad.toString()}
- >}
+ {Platform.OS === 'ios' && (
+ <>
+ isPad
+ {Platform.isPad.toString()}
+ >
+ )}
Constants
{JSON.stringify(Platform.constants, null, 2)}
@@ -39,8 +41,8 @@ const styles = StyleSheet.create({
value: {
fontWeight: '600',
padding: 4,
- marginBottom: 8
- }
+ marginBottom: 8,
+ },
});
export default App;
@@ -54,8 +56,8 @@ export default App;
### `constants`
-```jsx
-Platform.constants;
+```tsx
+static constants: PlatformConstants;
```
Returns an object which contains all available common and specific constants related to the platform.
@@ -84,8 +86,8 @@ Returns an object which contains all available common and specific constants rel
### `isPad`
iOS
-```jsx
-Platform.isPad;
+```tsx
+static isPad: boolean;
```
Returns a boolean which defines if device is an iPad.
@@ -98,8 +100,8 @@ Returns a boolean which defines if device is an iPad.
### `isTV`
-```jsx
-Platform.isTV;
+```tsx
+static isTV: boolean;
```
Returns a boolean which defines if device is a TV.
@@ -112,8 +114,8 @@ Returns a boolean which defines if device is a TV.
### `isTesting`
-```jsx
-Platform.isTesting;
+```tsx
+static isTesting: boolean;
```
Returns a boolean which defines if application is running in Developer Mode with testing flag set.
@@ -126,8 +128,8 @@ Returns a boolean which defines if application is running in Developer Mode with
### `OS`
-```jsx
-static Platform.OS
+```tsx
+static OS: 'android' | 'ios';
```
Returns string value representing the current OS.
@@ -140,8 +142,8 @@ Returns string value representing the current OS.
### `Version`
-```jsx
-Platform.Version;
+```tsx
+static Version: 'number' | 'string';
```
Returns the version of the OS.
@@ -154,8 +156,8 @@ Returns the version of the OS.
### `select()`
-```jsx
-static select(config: object): any
+```tsx
+static select(config: Record): T;
```
Returns the most fitting value for the platform you are currently running on.
@@ -177,25 +179,25 @@ The `config` parameter is an object with the following keys:
**Example usage:**
-```jsx
-import { Platform, StyleSheet } from 'react-native';
+```tsx
+import {Platform, StyleSheet} from 'react-native';
const styles = StyleSheet.create({
container: {
flex: 1,
...Platform.select({
android: {
- backgroundColor: 'green'
+ backgroundColor: 'green',
},
ios: {
- backgroundColor: 'red'
+ backgroundColor: 'red',
},
default: {
// other platforms, web for example
- backgroundColor: 'blue'
- }
- })
- }
+ backgroundColor: 'blue',
+ },
+ }),
+ },
});
```
@@ -203,19 +205,19 @@ This will result in a container having `flex: 1` on all platforms, a green backg
Since the value of the corresponding platform key can be of type `any`, [`select`](platform.md#select) method can also be used to return platform-specific components, like below:
-```jsx
+```tsx
const Component = Platform.select({
ios: () => require('ComponentIOS'),
- android: () => require('ComponentAndroid')
+ android: () => require('ComponentAndroid'),
})();
;
```
-```jsx
+```tsx
const Component = Platform.select({
native: () => require('ComponentForNative'),
- default: () => require('ComponentForWeb')
+ default: () => require('ComponentForWeb'),
})();
;
diff --git a/docs/platformcolor.md b/docs/platformcolor.md
index d5f97d4009b..422e0096c4c 100644
--- a/docs/platformcolor.md
+++ b/docs/platformcolor.md
@@ -45,19 +45,11 @@ For a full list of the types of system colors supported, see:
```SnackPlayer name=PlatformColor%20Example&supportedPlatforms=android,ios
import React from 'react';
-import {
- Platform,
- PlatformColor,
- StyleSheet,
- Text,
- View
-} from 'react-native';
+import {Platform, PlatformColor, StyleSheet, Text, View} from 'react-native';
const App = () => (
-
- I am a special label color!
-
+ I am a special label color!
);
@@ -67,22 +59,20 @@ const styles = StyleSheet.create({
...Platform.select({
ios: {
color: PlatformColor('label'),
- backgroundColor:
- PlatformColor('systemTealColor'),
+ backgroundColor: PlatformColor('systemTealColor'),
},
android: {
color: PlatformColor('?android:attr/textColor'),
- backgroundColor:
- PlatformColor('@android:color/holo_blue_bright'),
+ backgroundColor: PlatformColor('@android:color/holo_blue_bright'),
},
- default: { color: 'black' }
- })
+ default: {color: 'black'},
+ }),
},
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
- }
+ },
});
export default App;
diff --git a/docs/pressable.md b/docs/pressable.md
index d81298a4187..63cf09ac0c1 100644
--- a/docs/pressable.md
+++ b/docs/pressable.md
@@ -5,7 +5,7 @@ title: Pressable
Pressable is a Core Component wrapper that can detect various stages of press interactions on any of its defined children.
-```jsx
+```tsx
I'm pressable!
@@ -43,8 +43,8 @@ Fingers are not the most precise instruments, and it is common for users to acci
## Example
```SnackPlayer name=Pressable
-import React, { useState } from 'react';
-import { Pressable, StyleSheet, Text, View } from 'react-native';
+import React, {useState} from 'react';
+import {Pressable, StyleSheet, Text, View} from 'react-native';
const App = () => {
const [timesPressed, setTimesPressed] = useState(0);
@@ -60,20 +60,16 @@ const App = () => {
{
- setTimesPressed((current) => current + 1);
+ setTimesPressed(current => current + 1);
}}
- style={({ pressed }) => [
+ style={({pressed}) => [
{
- backgroundColor: pressed
- ? 'rgb(210, 230, 255)'
- : 'white'
+ backgroundColor: pressed ? 'rgb(210, 230, 255)' : 'white',
},
- styles.wrapperCustom
+ styles.wrapperCustom,
]}>
- {({ pressed }) => (
-
- {pressed ? 'Pressed!' : 'Press Me'}
-
+ {({pressed}) => (
+ {pressed ? 'Pressed!' : 'Press Me'}
)}
@@ -86,22 +82,22 @@ const App = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center",
+ justifyContent: 'center',
},
text: {
- fontSize: 16
+ fontSize: 16,
},
wrapperCustom: {
borderRadius: 8,
- padding: 6
+ padding: 6,
},
logBox: {
padding: 20,
margin: 10,
borderWidth: StyleSheet.hairlineWidth,
borderColor: '#f0f0f0',
- backgroundColor: '#f9f9f9'
- }
+ backgroundColor: '#f9f9f9',
+ },
});
export default App;
@@ -169,41 +165,41 @@ Sets additional distance outside of element in which a press can be detected.
Called if the time after `onPressIn` lasts longer than 500 milliseconds. This time period can be customized with [`delayLongPress`](#delaylongpress).
-| Type |
-| --------------------------------------------------- |
-| ({ nativeEvent: [PressEvent](pressevent) }) => void |
+| Type |
+| ------------------------------------------------- |
+| ({nativeEvent: [PressEvent](pressevent)}) => void |
### `onPress`
Called after `onPressOut`.
-| Type |
-| --------------------------------------------------- |
-| ({ nativeEvent: [PressEvent](pressevent) }) => void |
+| Type |
+| ------------------------------------------------- |
+| ({nativeEvent: [PressEvent](pressevent)}) => void |
### `onPressIn`
Called immediately when a touch is engaged, before `onPressOut` and `onPress`.
-| Type |
-| --------------------------------------------------- |
-| ({ nativeEvent: [PressEvent](pressevent) }) => void |
+| Type |
+| ------------------------------------------------- |
+| ({nativeEvent: [PressEvent](pressevent)}) => void |
### `onPressOut`
Called when a touch is released.
-| Type |
-| --------------------------------------------------- |
-| ({ nativeEvent: [PressEvent](pressevent) }) => void |
+| Type |
+| ------------------------------------------------- |
+| ({nativeEvent: [PressEvent](pressevent)}) => void |
### `pressRetentionOffset`
Additional distance outside of this view in which a touch is considered a press before `onPressOut` is triggered.
-| Type | Default |
-| ---------------------- | ---------------------------------------------- |
-| [Rect](rect) or number | `{ bottom: 30, left: 20, right: 20, top: 20 }` |
+| Type | Default |
+| ---------------------- | -------------------------------------------- |
+| [Rect](rect) or number | `{bottom: 30, left: 20, right: 20, top: 20}` |
### `style`
diff --git a/docs/profile-hermes.md b/docs/profile-hermes.md
index c16793cf18a..dd42869fe65 100644
--- a/docs/profile-hermes.md
+++ b/docs/profile-hermes.md
@@ -81,7 +81,7 @@ The Hermes Sample Profile is of the `JSON object format`, while the format that
export interface HermesCPUProfile {
traceEvents: SharedEventProperties[];
samples: HermesSample[];
- stackFrames: { [key in string]: HermesStackFrame };
+ stackFrames: {[key in string]: HermesStackFrame};
}
```
diff --git a/docs/progressbarandroid.md b/docs/progressbarandroid.md
index d869ed2f44b..ba5ee781a2a 100644
--- a/docs/progressbarandroid.md
+++ b/docs/progressbarandroid.md
@@ -38,7 +38,7 @@ const App = () => {
);
-}
+};
const styles = StyleSheet.create({
container: {
diff --git a/docs/progressviewios.md b/docs/progressviewios.md
index bff223cc507..312c202596e 100644
--- a/docs/progressviewios.md
+++ b/docs/progressviewios.md
@@ -38,7 +38,7 @@ const App = () => {
);
-}
+};
const styles = StyleSheet.create({
container: {
diff --git a/docs/props.md b/docs/props.md
index d320d4cc4ec..742b2d2d3af 100644
--- a/docs/props.md
+++ b/docs/props.md
@@ -3,22 +3,24 @@ id: props
title: Props
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
Most components can be customized when they are created, with different parameters. These created parameters are called `props`, short for properties.
For example, one basic React Native component is the `Image`. When you create an image, you can use a prop named `source` to control what image it shows.
```SnackPlayer name=Props
import React from 'react';
-import { Image } from 'react-native';
+import {Image} from 'react-native';
const Bananas = () => {
- let pic = {
- uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'
- };
- return (
-
- );
-}
+ let pic = {
+ uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg',
+ };
+ return (
+
+ );
+};
export default Bananas;
```
@@ -27,29 +29,69 @@ Notice the braces surrounding `{pic}` - these embed the variable `pic` into JSX.
Your own components can also use `props`. This lets you make a single component that is used in many different places in your app, with slightly different properties in each place by referring to `props` in your `render` function. Here's an example:
-```SnackPlayer name=Props
+
+
+
+```SnackPlayer name=Props&ext=js
import React from 'react';
-import { Text, View } from 'react-native';
-
-const Greeting = (props) => {
- return (
-
- Hello {props.name}!
-
- );
-}
-
-export default LotsOfGreetings = () => {
- return (
-
-
-
-
-
- );
-}
+import {Text, View} from 'react-native';
+
+const Greeting = props => {
+ return (
+
+ Hello {props.name}!
+
+ );
+};
+
+const LotsOfGreetings = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+export default LotsOfGreetings;
```
+
+
+
+```SnackPlayer name=Props&ext=tsx
+import React from 'react';
+import {Text, View} from 'react-native';
+
+type GreetingsProps = {
+ name: string;
+};
+
+const Greeting = (props: GreetingsProps) => {
+ return (
+
+ Hello {props.name}!
+
+ );
+};
+
+const LotsOfGreetings = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+export default LotsOfGreetings;
+```
+
+
+
+
Using `name` as a prop lets us customize the `Greeting` component, so we can reuse that component for each of our greetings. This example also uses the `Greeting` component in JSX, similar to the [Core Components](intro-react-native-components). The power to do this is what makes React so cool - if you find yourself wishing that you had a different set of UI primitives to work with, you can invent new ones.
The other new thing going on here is the [`View`](view.md) component. A [`View`](view.md) is useful as a container for other components, to help control style and layout.
diff --git a/docs/pushnotificationios.md b/docs/pushnotificationios.md
index 8a801b3ccbe..9cbb9476757 100644
--- a/docs/pushnotificationios.md
+++ b/docs/pushnotificationios.md
@@ -112,8 +112,8 @@ Then enable Background Modes/Remote notifications to be able to use remote notif
### `presentLocalNotification()`
-```jsx
-PushNotificationIOS.presentLocalNotification(details);
+```tsx
+static presentLocalNotification(details: PresentLocalNotificationDetails);
```
Schedules the localNotification for immediate presentation.
@@ -139,8 +139,8 @@ details is an object containing:
### `scheduleLocalNotification()`
-```jsx
-PushNotificationIOS.scheduleLocalNotification(details);
+```tsx
+static scheduleLocalNotification(details: ScheduleLocalNotificationDetails);
```
Schedules the localNotification for future presentation.
@@ -168,8 +168,8 @@ details is an object containing:
### `cancelAllLocalNotifications()`
-```jsx
-PushNotificationIOS.cancelAllLocalNotifications();
+```tsx
+static cancelAllLocalNotifications();
```
Cancels all scheduled localNotifications
@@ -178,8 +178,8 @@ Cancels all scheduled localNotifications
### `removeAllDeliveredNotifications()`
-```jsx
-PushNotificationIOS.removeAllDeliveredNotifications();
+```tsx
+static removeAllDeliveredNotifications();
```
Remove all delivered notifications from Notification Center
@@ -188,8 +188,8 @@ Remove all delivered notifications from Notification Center
### `getDeliveredNotifications()`
-```jsx
-PushNotificationIOS.getDeliveredNotifications(callback);
+```tsx
+static getDeliveredNotifications(callback: (notifications: Object[]) => void);
```
Provides you with a list of the appâs notifications that are still displayed in Notification Center
@@ -213,8 +213,8 @@ A delivered notification is an object containing:
### `removeDeliveredNotifications()`
-```jsx
-PushNotificationIOS.removeDeliveredNotifications(identifiers);
+```tsx
+static removeDeliveredNotifications(identifiers: string[]);
```
Removes the specified notifications from Notification Center
@@ -229,8 +229,8 @@ Removes the specified notifications from Notification Center
### `setApplicationIconBadgeNumber()`
-```jsx
-PushNotificationIOS.setApplicationIconBadgeNumber(number);
+```tsx
+static setApplicationIconBadgeNumber(number: number);
```
Sets the badge number for the app icon on the home screen
@@ -245,8 +245,8 @@ Sets the badge number for the app icon on the home screen
### `getApplicationIconBadgeNumber()`
-```jsx
-PushNotificationIOS.getApplicationIconBadgeNumber(callback);
+```tsx
+static getApplicationIconBadgeNumber(callback: (badge: number) => void);
```
Gets the current badge number for the app icon on the home screen
@@ -261,8 +261,8 @@ Gets the current badge number for the app icon on the home screen
### `cancelLocalNotifications()`
-```jsx
-PushNotificationIOS.cancelLocalNotifications(userInfo);
+```tsx
+static cancelLocalNotifications(userInfo: Object);
```
Cancel local notifications.
@@ -279,8 +279,10 @@ Optionally restricts the set of canceled notifications to those notifications wh
### `getScheduledLocalNotifications()`
-```jsx
-PushNotificationIOS.getScheduledLocalNotifications(callback);
+```tsx
+static getScheduledLocalNotifications(
+ callback: (notifications: ScheduleLocalNotificationDetails[]) => void,
+);
```
Gets the local notifications that are currently scheduled.
@@ -295,8 +297,14 @@ Gets the local notifications that are currently scheduled.
### `addEventListener()`
-```jsx
-PushNotificationIOS.addEventListener(type, handler);
+```tsx
+static addEventListener(
+ type: PushNotificationEventName,
+ handler:
+ | ((notification: PushNotification) => void)
+ | ((deviceToken: string) => void)
+ | ((error: {message: string; code: number; details: any}) => void),
+);
```
Attaches a listener to remote or local notification events while the app is running in the foreground or the background.
@@ -319,8 +327,14 @@ Valid events are:
### `removeEventListener()`
-```jsx
-PushNotificationIOS.removeEventListener(type, handler);
+```tsx
+static removeEventListener(
+ type: PushNotificationEventName,
+ handler:
+ | ((notification: PushNotification) => void)
+ | ((deviceToken: string) => void)
+ | ((error: {message: string; code: number; details: any}) => void),
+);
```
Removes the event listener. Do this in `componentWillUnmount` to prevent memory leaks
@@ -336,8 +350,8 @@ Removes the event listener. Do this in `componentWillUnmount` to prevent memory
### `requestPermissions()`
-```jsx
-PushNotificationIOS.requestPermissions([permissions]);
+```tsx
+static requestPermissions(permissions?: PushNotificationPermissions[]);
```
Requests notification permissions from iOS, prompting the user's dialog box. By default, it will request all notification permissions, but a subset of these can be requested by passing a map of requested permissions. The following permissions are supported:
@@ -360,8 +374,8 @@ This method returns a promise that will resolve when the user accepts, rejects,
### `abandonPermissions()`
-```jsx
-PushNotificationIOS.abandonPermissions();
+```tsx
+static abandonPermissions();
```
Unregister for all remote notifications received via Apple Push Notification service.
@@ -372,8 +386,10 @@ You should call this method in rare circumstances only, such as when a new versi
### `checkPermissions()`
-```jsx
-PushNotificationIOS.checkPermissions(callback);
+```tsx
+static checkPermissions(
+ callback: (permissions: PushNotificationPermissions) => void,
+);
```
See what push permissions are currently enabled.
@@ -394,28 +410,18 @@ See what push permissions are currently enabled.
### `getInitialNotification()`
-```jsx
-PushNotificationIOS.getInitialNotification();
+```tsx
+static getInitialNotification(): Promise;
```
This method returns a promise. If the app was launched by a push notification, this promise resolves to an object of type `PushNotificationIOS`. Otherwise, it resolves to `null`.
---
-### `constructor()`
-
-```jsx
-constructor(nativeNotif);
-```
-
-You will never need to instantiate `PushNotificationIOS` yourself. Listening to the `notification` event and invoking `getInitialNotification` is sufficient.
-
----
-
### `finish()`
-```jsx
-finish(fetchResult);
+```tsx
+finish(result: string);
```
This method is available for remote notifications that have been received via: `application:didReceiveRemoteNotification:fetchCompletionHandler:` https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application?language=objc
@@ -428,8 +434,8 @@ If you do not call this method your background remote notifications could be thr
### `getMessage()`
-```jsx
-getMessage();
+```tsx
+getMessage(): string | Object;
```
An alias for `getAlert` to get the notification's main message string
@@ -438,8 +444,8 @@ An alias for `getAlert` to get the notification's main message string
### `getSound()`
-```jsx
-getSound();
+```tsx
+getSound(): string;
```
Gets the sound string from the `aps` object
@@ -448,8 +454,8 @@ Gets the sound string from the `aps` object
### `getCategory()`
-```jsx
-getCategory();
+```tsx
+getCategory(): string;
```
Gets the category string from the `aps` object
@@ -458,8 +464,8 @@ Gets the category string from the `aps` object
### `getAlert()`
-```jsx
-getAlert();
+```tsx
+getAlert(): string | Object;
```
Gets the notification's main message from the `aps` object
@@ -468,8 +474,8 @@ Gets the notification's main message from the `aps` object
### `getContentAvailable()`
-```jsx
-getContentAvailable();
+```tsx
+getContentAvailable(): number;
```
Gets the content-available number from the `aps` object
@@ -478,8 +484,8 @@ Gets the content-available number from the `aps` object
### `getBadgeCount()`
-```jsx
-getBadgeCount();
+```tsx
+getBadgeCount(): number;
```
Gets the badge count number from the `aps` object
@@ -488,8 +494,8 @@ Gets the badge count number from the `aps` object
### `getData()`
-```jsx
-getData();
+```tsx
+getData(): Object;
```
Gets the data object on the notification
@@ -498,7 +504,7 @@ Gets the data object on the notification
### `getThreadID()`
-```jsx
+```tsx
getThreadID();
```
diff --git a/docs/ram-bundles-inline-requires.md b/docs/ram-bundles-inline-requires.md
index d63a2bc7303..b7f5ba9e912 100644
--- a/docs/ram-bundles-inline-requires.md
+++ b/docs/ram-bundles-inline-requires.md
@@ -13,9 +13,9 @@ Before react-native can execute JS code, that code must be loaded into memory an
Inline requires delay the requiring of a module or file until that file is actually needed. A basic example would look like this:
-```js title='VeryExpensive.js'
-import React, { Component } from 'react';
-import { Text } from 'react-native';
+```tsx title="VeryExpensive.tsx"
+import React, {Component} from 'react';
+import {Text} from 'react-native';
// ... import some very expensive modules
// You may want to log at the file level to verify when this is happening
@@ -29,14 +29,14 @@ export default class VeryExpensive extends Component {
}
```
-```js title='Optimized.js'
-import React, { Component } from 'react';
-import { TouchableOpacity, View, Text } from 'react-native';
+```tsx title="Optimized.tsx"
+import React, {Component} from 'react';
+import {TouchableOpacity, View, Text} from 'react-native';
let VeryExpensive = null;
export default class Optimized extends Component {
- state = { needsExpensive: false };
+ state = {needsExpensive: false};
didPress = () => {
if (VeryExpensive == null) {
@@ -44,13 +44,13 @@ export default class Optimized extends Component {
}
this.setState(() => ({
- needsExpensive: true
+ needsExpensive: true,
}));
};
render() {
return (
-
+ Load
@@ -108,18 +108,18 @@ In your root file (index.(ios|android).js) you can add the following after the i
const modules = require.getModules();
const moduleIds = Object.keys(modules);
const loadedModuleNames = moduleIds
- .filter((moduleId) => modules[moduleId].isInitialized)
- .map((moduleId) => modules[moduleId].verboseName);
+ .filter(moduleId => modules[moduleId].isInitialized)
+ .map(moduleId => modules[moduleId].verboseName);
const waitingModuleNames = moduleIds
- .filter((moduleId) => !modules[moduleId].isInitialized)
- .map((moduleId) => modules[moduleId].verboseName);
+ .filter(moduleId => !modules[moduleId].isInitialized)
+ .map(moduleId => modules[moduleId].verboseName);
// make sure that the modules you expect to be waiting are actually waiting
console.log(
'loaded:',
loadedModuleNames.length,
'waiting:',
- waitingModuleNames.length
+ waitingModuleNames.length,
);
// grab this text blob, and put it in a file named packager/modulePaths.js
@@ -127,15 +127,15 @@ console.log(
`module.exports = ${JSON.stringify(
loadedModuleNames.sort(),
null,
- 2
- )};`
+ 2,
+ )};`,
);
```
When you run your app, you can look in the console and see how many modules have been loaded, and how many are waiting. You may want to read the moduleNames and see if there are any surprises. Note that inline requires are invoked the first time the imports are referenced. You may need to investigate and refactor to ensure only the modules you want are loaded on startup. Note that you can change the Systrace object on require to help debug problematic requires.
```js
-require.Systrace.beginEvent = (message) => {
+require.Systrace.beginEvent = message => {
if (message.includes(problematicModule)) {
throw new Error();
}
@@ -160,18 +160,18 @@ const config = {
transformer: {
getTransformOptions: () => {
const moduleMap = {};
- modulePaths.forEach((path) => {
+ modulePaths.forEach(path => {
if (fs.existsSync(path)) {
moduleMap[resolve(path)] = true;
}
});
return {
preloadedModules: moduleMap,
- transform: { inlineRequires: { blockList: moduleMap } }
+ transform: {inlineRequires: {blockList: moduleMap}},
};
- }
+ },
},
- projectRoot: ROOT_FOLDER
+ projectRoot: ROOT_FOLDER,
};
module.exports = config;
diff --git a/docs/react-native-gradle-plugin.md b/docs/react-native-gradle-plugin.md
new file mode 100644
index 00000000000..dd7e78c06ee
--- /dev/null
+++ b/docs/react-native-gradle-plugin.md
@@ -0,0 +1,187 @@
+---
+id: react-native-gradle-plugin
+title: React Native Gradle Plugin
+---
+
+This guide describes how to configure the **React Native Gradle Plugin** (often referred as RNGP), when building your React Native application for Android.
+
+## Using the plugin
+
+The React Native Gradle Plugin is distributed as a separate NPM package which is installed automatically with `react-native`.
+
+The plugin is **already configured** for new projects created using `npx react-native init`. You don't need to do any extra steps to install it if you created your app with this command.
+
+If you're integrating React Native into an existing project, please refer to [the corresponding page](/docs/next/integration-with-existing-apps#configuring-gradle): it contains specific instructions on how to install the plugin.
+
+## Configuring the plugin
+
+By default, the plugin will work **out of the box** with sensible defaults. You should refer to this guide and customize the behavior only if you need it.
+
+To configure the plugin you can modify a the `react` block, inside your `android/app/build.gradle`:
+
+```groovy
+apply plugin: "com.facebook.react"
+
+/**
+ * This is the configuration block to customize your React Native Android app.
+ * By default you don't need to apply any configuration, just uncomment the lines you need.
+ */
+react {
+ // Custom configuration goes here.
+}
+```
+
+Each configuration key is described below:
+
+### `root`
+
+This is the root folder of your React Native project, i.e. where the `package.json` file lives. Default is `..`. You can customize it as follows:
+
+```groovy
+root = file("../")
+```
+
+### `reactNativeDir`
+
+This is the folder where the `react-native` package lives. Default is `../node_modules/react-native`.
+If you're in a monorepo or using a different package manager, you can use adjust `reactNativeDir` to your setup.
+
+You can customize it as follows:
+
+```groovy
+reactNativeDir = file("../node_modules/react-native")
+```
+
+### `codegenDir`
+
+This is the folder where the `react-native-codegen` package lives. Default is `../node_modules/react-native-codegen`.
+If you're in a monorepo or using a different package manager, you can adjust `codegenDir` to your setup.
+
+You can customize it as follows:
+
+```groovy
+reactNativeDir = file("../node_modules/@react-native/codegen")
+```
+
+### `cliFile`
+
+This is the entrypoint file for the React Native CLI. Default is `../node_modules/react-native/cli.js`.
+The entrypoint file is needed as the plugin needs to invoke the CLI for bundling and creating your app.
+
+If you're in a monorepo or using a different package manager, you can adjust `cliFile` to your setup.
+You can customize it as follows:
+
+```groovy
+cliFile = file("../node_modules/react-native/cli.js")
+```
+
+### `debuggableVariants`
+
+This is the list of variants that are debuggable (see [using variants](#using-variants) for more context on variants).
+
+By default the plugin is considering as `debuggableVariants` only `debug`, while `release` is not. If you have other
+variants (like `staging`, `lite`, etc.) you'll need to adjust this accordingly.
+
+Variants that are listed as `debuggableVariants` will not come with a shipped bundle, so you'll need Metro to run them.
+
+You can customize it as follows:
+
+```groovy
+debuggableVariants = ["liteDebug", "prodDebug"]
+```
+
+### `nodeExecutableAndArgs`
+
+This is the list of node command and arguments that should be invoked for all the scripts. By default is `[node]` but can be customized to add extra flags as follows:
+
+```groovy
+nodeExecutableAndArgs = ["node"]
+```
+
+### `bundleCommand`
+
+This is the name of the `bundle` command to be invoked when creating the bundle for your app. That's useful if you're using [RAM Bundles](/docs/ram-bundles-inline-requires). By default is `bundle` but can be customized to add extra flags as follows:
+
+```groovy
+bundleCommand = "ram-bundle"
+```
+
+### `bundleConfig`
+
+This is the path to a configuration file that will be passed to `bundle --config ` if provided. Default is empty (no config file will be probided). More information on bundling config files can be found [on the CLI documentation](https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle). Can be customized as follow:
+
+```groovy
+bundleConfig = file(../rn-cli.config.js)
+```
+
+### `bundleAssetName`
+
+This is the name of the bundle file that should be generated. Default is `index.android.bundle`. Can be customized as follow:
+
+```groovy
+bundleAssetName = "MyApplication.android.bundle"
+```
+
+### `entryFile`
+
+The entry file used for bundle generation. The default is to search for `index.android.js` or `index.js`. Can be customized as follow:
+
+```groovy
+entryFile = file("../js/MyApplication.android.js")
+```
+
+### `extraPackagerArgs`
+
+A list of extra flags that will be passed to the `bundle` command. The list of available flags is in [the CLI documentation](https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle). Default is empty. Can be customized as follows:
+
+```groovy
+extraPackagerArgs = []
+```
+
+### `hermesCommand`
+
+The path to the `hermesc` command (the Hermes Compiler). React Native comes with a version of the Hermes compiler bundled with it, so you generally won't be needing to customize this. The plugin will use the correct compiler for your system by default.
+
+### `hermesFlags`
+
+The list of flags to pass to `hermesc`. By default is `["-O", "-output-source-map"]`. You can customize it as follows
+
+```groovy
+hermesFlags = ["-O", "-output-source-map"]
+```
+
+## Using Flavors & Build Variants
+
+When building Android apps, you might want to use [custom flavors](https://developer.android.com/studio/build/build-variants#product-flavors) to have different versions of your app starting from the same project.
+
+Please refer to the [official Android guide](https://developer.android.com/studio/build/build-variants) to configure custom build types (like `staging`) or custom flavors (like `full`, `lite`, etc.).
+By default new apps are create with two build types (`debug` and `release`) and no custom flavors.
+
+The combination of all the build types and all the flavors generates a set of **build variants**. For instance for `debug`/`staging`/`release` build types and `full`/`lite` you will have 6 build variants: `fullDebug`, `fullStaging`, `fullRelease` and so on.
+
+If you're using custom variants beyond `debug` and `release`, you need to instruct the React Native Gradle Plugin specifying which of your variants are **debuggable** using the [`debuggableVariants`](#debuggablevariants) configuration as follows:
+
+```diff
+apply plugin: "com.facebook.react"
+
+react {
++ debuggableVariants = ["fullStaging", "fullDebug"]
+}
+```
+
+This is necessary because the plugin will skip the JS bundling for all the `debuggableVariants`: you'll need Metro to run them. For example, if you list `fullStaging` in the `debuggableVariants`, you won't be able to publish it to a store as it will be missing the bundle.
+
+## What is the plugin doing under the hood?
+
+The React Native Gradle Plugin is responsible for configuring your Application build to ship React Native applications to production.
+The plugin is also used inside 3rd party libraries, to run the [Codegen](/docs/the-new-architecture/pillars-codegen) used for the New Architecture.
+
+Here is a summary of the plugin responsibilities:
+
+- Add a `createBundleJsAndAssets` task for every non debuggable variant, that is responsible of invoking the `bundle`, `hermesc` and `compose-source-map` commands.
+- Setting up the proper version of the `com.facebook.react:react-android` and `com.facebook.react:hermes-android` dependency, reading the React Native version from the `package.json` of `react-native`.
+- Setting up the proper Maven repositories (Maven Central, Google Maven Repo, JSC local Maven repo, etc.) needed to consume all the necessary Maven Dependencies.
+- Setting up the NDK to let you build apps that are using the New Architecture.
+- Setting up the `buildConfigFields` so that you can know at runtime if Hermes or the New Architecture are enabled.
+- Setting up the Metro DevServer Port as an Android resource so the app knows on which port to connect.
+- Invoking the [React Native Codegen](/docs/the-new-architecture/pillars-codegen) if a library or app is using the Codegen for the New Architecture.
diff --git a/docs/refreshcontrol.md b/docs/refreshcontrol.md
index eda2da25aad..c2c74ea2231 100644
--- a/docs/refreshcontrol.md
+++ b/docs/refreshcontrol.md
@@ -9,18 +9,22 @@ This component is used inside a ScrollView or ListView to add pull to refresh fu
```SnackPlayer name=RefreshControl&supportedPlatforms=ios,android
import React from 'react';
-import { RefreshControl, SafeAreaView, ScrollView, StyleSheet, Text } from 'react-native';
-
-const wait = (timeout) => {
- return new Promise(resolve => setTimeout(resolve, timeout));
-}
+import {
+ RefreshControl,
+ SafeAreaView,
+ ScrollView,
+ StyleSheet,
+ Text,
+} from 'react-native';
const App = () => {
const [refreshing, setRefreshing] = React.useState(false);
const onRefresh = React.useCallback(() => {
setRefreshing(true);
- wait(2000).then(() => setRefreshing(false));
+ setTimeout(() => {
+ setRefreshing(false);
+ }, 2000);
}, []);
return (
@@ -28,17 +32,13 @@ const App = () => {
- }
- >
+
+ }>
Pull down to see RefreshControl indicator
);
-}
+};
const styles = StyleSheet.create({
container: {
diff --git a/docs/roottag.md b/docs/roottag.md
index cd3e47e3c7b..c486b6f93c1 100644
--- a/docs/roottag.md
+++ b/docs/roottag.md
@@ -26,14 +26,14 @@ In versions 0.65 and below, RootTag is accessed via a [legacy context](https://g
How to access `RootTag` via the `RootTagContext`.
```js
-import { RootTagContext } from 'react-native';
+import {RootTagContext} from 'react-native';
import NativeAnalytics from 'native-analytics';
import NativeNavigation from 'native-navigation';
function ScreenA() {
const rootTag = useContext(RootTagContext);
- const updateTitle = (title) => {
+ const updateTitle = title => {
NativeNavigation.setTitle(rootTag, title);
};
diff --git a/docs/safeareaview.md b/docs/safeareaview.md
index 4ccf60d8628..16c3acdd33b 100644
--- a/docs/safeareaview.md
+++ b/docs/safeareaview.md
@@ -13,7 +13,7 @@ To use, wrap your top level view with a `SafeAreaView` with a `flex: 1` style ap
```SnackPlayer name=SafeAreaView&supportedPlatforms=ios
import React from 'react';
-import { StyleSheet, Text, SafeAreaView } from 'react-native';
+import {StyleSheet, Text, SafeAreaView} from 'react-native';
const App = () => {
return (
@@ -21,7 +21,7 @@ const App = () => {
Page content
);
-}
+};
const styles = StyleSheet.create({
container: {
@@ -30,7 +30,7 @@ const styles = StyleSheet.create({
text: {
fontSize: 25,
fontWeight: '500',
- }
+ },
});
export default App;
diff --git a/docs/scrollview.md b/docs/scrollview.md
index 952b9e9f83a..6c03d431f67 100644
--- a/docs/scrollview.md
+++ b/docs/scrollview.md
@@ -23,7 +23,13 @@ This is where `FlatList` comes into play. `FlatList` renders items lazily, when
```SnackPlayer name=ScrollView
import React from 'react';
-import { StyleSheet, Text, SafeAreaView, ScrollView, StatusBar } from 'react-native';
+import {
+ StyleSheet,
+ Text,
+ SafeAreaView,
+ ScrollView,
+ StatusBar,
+} from 'react-native';
const App = () => {
return (
@@ -41,7 +47,7 @@ const App = () => {
);
-}
+};
const styles = StyleSheet.create({
container: {
@@ -367,9 +373,9 @@ Caveat 1: Reordering elements in the scrollview with this enabled will probably
Caveat 2: This uses `contentOffset` and `frame.origin` in native code to compute visibility. Occlusion, transforms, and other complexity won't be taken into account as to whether content is "visible" or not.
-| Type |
-| ------------------------------------------------------------------------ |
-| object: { minIndexForVisible: number, autoscrollToTopThreshold: number } |
+| Type |
+| ---------------------------------------------------------------------- |
+| object: {minIndexForVisible: number, autoscrollToTopThreshold: number} |
---
@@ -731,7 +737,7 @@ The current scale of the scroll view content.
### `flashScrollIndicators()`
-```jsx
+```tsx
flashScrollIndicators();
```
@@ -741,9 +747,9 @@ Displays the scroll indicators momentarily.
### `scrollTo()`
-```jsx
+```tsx
scrollTo(
- options?: { x?: number, y?: number, animated?: boolean } | number,
+ options?: {x?: number, y?: number, animated?: boolean} | number,
deprecatedX?: number,
deprecatedAnimated?: boolean,
);
@@ -753,7 +759,7 @@ Scrolls to a given x, y offset, either immediately, with a smooth animation.
**Example:**
-`scrollTo({ x: 0, y: 0, animated: true })`
+`scrollTo({x: 0, y: 0, animated: true})`
> Note: The weird function signature is due to the fact that, for historical reasons, the function also accepts separate arguments as an alternative to the options object. This is deprecated due to ambiguity (y before x), and SHOULD NOT BE USED.
@@ -761,10 +767,10 @@ Scrolls to a given x, y offset, either immediately, with a smooth animation.
### `scrollToEnd()`
-```jsx
-scrollToEnd(([options]: { animated: boolean }));
+```tsx
+scrollToEnd(options?: {animated?: boolean});
```
If this is a vertical ScrollView scrolls to the bottom. If this is a horizontal ScrollView scrolls to the right.
-Use `scrollToEnd({ animated: true })` for smooth animated scrolling, `scrollToEnd({ animated: false })` for immediate scrolling. If no options are passed, `animated` defaults to `true`.
+Use `scrollToEnd({animated: true})` for smooth animated scrolling, `scrollToEnd({animated: false})` for immediate scrolling. If no options are passed, `animated` defaults to `true`.
diff --git a/docs/sectionlist.md b/docs/sectionlist.md
index 5b28b31c62d..bc82fc6029e 100644
--- a/docs/sectionlist.md
+++ b/docs/sectionlist.md
@@ -26,41 +26,46 @@ If you don't need section support and want a simpler interface, use [`
```SnackPlayer name=SectionList%20Example
-import React from "react";
-import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native";
+import React from 'react';
+import {
+ StyleSheet,
+ Text,
+ View,
+ SafeAreaView,
+ SectionList,
+ StatusBar,
+} from 'react-native';
const DATA = [
{
- title: "Main dishes",
- data: ["Pizza", "Burger", "Risotto"]
+ title: 'Main dishes',
+ data: ['Pizza', 'Burger', 'Risotto'],
},
{
- title: "Sides",
- data: ["French Fries", "Onion Rings", "Fried Shrimps"]
+ title: 'Sides',
+ data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
},
{
- title: "Drinks",
- data: ["Water", "Coke", "Beer"]
+ title: 'Drinks',
+ data: ['Water', 'Coke', 'Beer'],
},
{
- title: "Desserts",
- data: ["Cheese Cake", "Ice Cream"]
- }
+ title: 'Desserts',
+ data: ['Cheese Cake', 'Ice Cream'],
+ },
];
-const Item = ({ title }) => (
-
- {title}
-
-);
-
const App = () => (
item + index}
- renderItem={({ item }) => }
- renderSectionHeader={({ section: { title } }) => (
+ renderItem={({item}) => (
+
+ {item}
+
+ )}
+ renderSectionHeader={({section: {title}}) => (
{title}
)}
/>
@@ -71,20 +76,20 @@ const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: StatusBar.currentHeight,
- marginHorizontal: 16
+ marginHorizontal: 16,
},
item: {
- backgroundColor: "#f9c2ff",
+ backgroundColor: '#f9c2ff',
padding: 20,
- marginVertical: 8
+ marginVertical: 8,
},
header: {
fontSize: 32,
- backgroundColor: "#fff"
+ backgroundColor: '#fff',
},
title: {
- fontSize: 24
- }
+ fontSize: 24,
+ },
});
export default App;
@@ -94,34 +99,35 @@ export default App;
```SnackPlayer name=SectionList%20Example
-import React, { Component } from "react";
-import { StyleSheet, Text, View, SafeAreaView, SectionList, StatusBar } from "react-native";
+import React, {Component} from 'react';
+import {
+ StyleSheet,
+ Text,
+ View,
+ SafeAreaView,
+ SectionList,
+ StatusBar,
+} from 'react-native';
const DATA = [
{
- title: "Main dishes",
- data: ["Pizza", "Burger", "Risotto"]
+ title: 'Main dishes',
+ data: ['Pizza', 'Burger', 'Risotto'],
},
{
- title: "Sides",
- data: ["French Fries", "Onion Rings", "Fried Shrimps"]
+ title: 'Sides',
+ data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
},
{
- title: "Drinks",
- data: ["Water", "Coke", "Beer"]
+ title: 'Drinks',
+ data: ['Water', 'Coke', 'Beer'],
},
{
- title: "Desserts",
- data: ["Cheese Cake", "Ice Cream"]
- }
+ title: 'Desserts',
+ data: ['Cheese Cake', 'Ice Cream'],
+ },
];
-const Item = ({ title }) => (
-
- {title}
-
-);
-
class App extends Component {
render() {
return (
@@ -129,8 +135,12 @@ class App extends Component {
item + index}
- renderItem={({ item }) => }
- renderSectionHeader={({ section: { title } }) => (
+ renderItem={({item}) => (
+
+ {item}
+
+ )}
+ renderSectionHeader={({section: {title}}) => (
{title}
)}
/>
@@ -143,20 +153,20 @@ const styles = StyleSheet.create({
container: {
flex: 1,
paddingTop: StatusBar.currentHeight,
- marginHorizontal: 16
+ marginHorizontal: 16,
},
item: {
- backgroundColor: "#f9c2ff",
+ backgroundColor: '#f9c2ff',
padding: 20,
- marginVertical: 8
+ marginVertical: 8,
},
header: {
fontSize: 32,
- backgroundColor: "#fff"
+ backgroundColor: '#fff',
},
title: {
- fontSize: 24
- }
+ fontSize: 24,
+ },
});
export default App;
@@ -300,9 +310,9 @@ Rendered at the very beginning of the list. Can be a React Component (e.g. `Some
Called once when the scroll position gets within `onEndReachedThreshold` of the rendered content.
-| Type |
-| ------------------------------------------- |
-| (info: { distanceFromEnd: number }) => void |
+| Type |
+| ----------------------------------------- |
+| (info: {distanceFromEnd: number}) => void |
---
@@ -330,9 +340,9 @@ If provided, a standard RefreshControl will be added for "Pull to Refresh" funct
Called when the viewability of rows changes, as defined by the `viewabilityConfig` prop.
-| Type |
-| ------------------------------------------------------------------------------------------------------------------ |
-| (callback: { changed: array of [ViewToken](viewtoken)s, viewableItems: array of [ViewToken](viewtoken)s }) => void |
+| Type |
+| ---------------------------------------------------------------------------------------------------------------- |
+| (callback: {changed: array of [ViewToken](viewtoken)s, viewableItems: array of [ViewToken](viewtoken)s}) => void |
---
@@ -362,9 +372,9 @@ This may improve scroll performance for large lists.
Rendered at the bottom of each section.
-| Type |
-| ---------------------------------------------------------------------- |
-| (info: { section: [Section](sectionlist#section) }) => element, `null` |
+| Type |
+| -------------------------------------------------------------------- |
+| (info: {section: [Section](sectionlist#section)}) => element, `null` |
---
@@ -372,9 +382,9 @@ Rendered at the bottom of each section.
Rendered at the top of each section. These stick to the top of the `ScrollView` by default on iOS. See `stickySectionHeadersEnabled`.
-| Type |
-| ---------------------------------------------------------------------- |
-| (info: { section: [Section](sectionlist#section) }) => element, `null` |
+| Type |
+| -------------------------------------------------------------------- |
+| (info: {section: [Section](sectionlist#section)}) => element, `null` |
---
@@ -400,7 +410,7 @@ Makes section headers stick to the top of the screen until the next one pushes i
### `flashScrollIndicators()`
iOS
-```jsx
+```tsx
flashScrollIndicators();
```
@@ -410,7 +420,7 @@ Displays the scroll indicators momentarily.
### `recordInteraction()`
-```jsx
+```tsx
recordInteraction();
```
@@ -420,8 +430,8 @@ Tells the list an interaction has occurred, which should trigger viewability cal
### `scrollToLocation()`
-```jsx
-scrollToLocation(params);
+```tsx
+scrollToLocation(params: SectionListScrollParams);
```
Scrolls to the item at the specified `sectionIndex` and `itemIndex` (within the section) positioned in the viewable area such that `viewPosition` 0 places it at the top (and may be covered by a sticky header), 1 at the bottom, and 0.5 centered in the middle.
diff --git a/docs/segmentedcontrolios.md b/docs/segmentedcontrolios.md
index f04589176ae..eb7ec3a49d3 100644
--- a/docs/segmentedcontrolios.md
+++ b/docs/segmentedcontrolios.md
@@ -3,7 +3,7 @@ id: segmentedcontrolios
title: 'đ§ SegmentedControlIOS'
---
-> **Deprecated.** Use one of the [community packages](https://reactnative.directory/?search=segmentedcontrol) instead.
+> **Removed from React Native.** Use one of the [community packages](https://reactnative.directory/?search=segmentedcontrol) instead.
Uses `SegmentedControlIOS` to render a UISegmentedControl iOS.
@@ -13,24 +13,22 @@ The selected index can be changed on the fly by assigning the selectedIndex prop
## Example
-```SnackPlayer name=SegmentedControlIOS%20Example&supportedPlatforms=ios
-import React, { useState } from "react";
-import { SegmentedControlIOS, StyleSheet, Text, View } from "react-native";
+```SnackPlayer name=SegmentedControlIOS%20Example&supportedPlatforms=ios&ext=js
+import React, {useState} from 'react';
+import {SegmentedControlIOS, StyleSheet, Text, View} from 'react-native';
-export default App = () => {
+const App = () => {
const [index, setIndex] = useState(0);
return (
{
+ onChange={event => {
setIndex(event.nativeEvent.selectedSegmentIndex);
}}
/>
-
- Selected index: {index}
-
+ Selected index: {index}
);
};
@@ -39,12 +37,14 @@ const styles = StyleSheet.create({
container: {
flex: 1,
padding: 24,
- justifyContent: "center"
+ justifyContent: 'center',
},
text: {
- marginTop: 24
- }
+ marginTop: 24,
+ },
});
+
+export default App;
```
---
diff --git a/docs/settings.md b/docs/settings.md
index bff84732576..76aabe647b7 100644
--- a/docs/settings.md
+++ b/docs/settings.md
@@ -8,27 +8,28 @@ title: Settings
## Example
```SnackPlayer name=Settings%20Example&supportedPlatforms=ios
-import React, { useState } from "react";
-import { Button, Settings, StyleSheet, Text, View } from "react-native";
+import React, {useState} from 'react';
+import {Button, Settings, StyleSheet, Text, View} from 'react-native';
const App = () => {
- const [data, setData] = useState(Settings.get("data"));
-
- const storeData = data => {
- Settings.set(data);
- setData(Settings.get("data"));
- };
+ const [data, setData] = useState(() => Settings.get('data'));
return (
Stored value:{data} storeData({ data: "React" })}
+ onPress={() => {
+ Settings.set({data: 'React'});
+ setData(Settings.get('data'));
+ }}
title="Store 'React'"
/>
storeData({ data: "Native" })}
+ onPress={() => {
+ Settings.set({data: 'Native'});
+ setData(Settings.get('data'));
+ }}
title="Store 'Native'"
/>
@@ -38,13 +39,13 @@ const App = () => {
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "center",
- alignItems: "center"
+ justifyContent: 'center',
+ alignItems: 'center',
},
value: {
fontSize: 24,
- marginVertical: 12
- }
+ marginVertical: 12,
+ },
});
export default App;
@@ -58,8 +59,8 @@ export default App;
### `clearWatch()`
-```jsx
-static clearWatch(watchId: number)
+```tsx
+static clearWatch(watchId: number);
```
`watchId` is the number returned by `watchKeys()` when the subscription was originally configured.
@@ -68,8 +69,8 @@ static clearWatch(watchId: number)
### `get()`
-```jsx
-static get(key: string): mixed
+```tsx
+static get(key: string): any;
```
Get the current value for a given `key` in `NSUserDefaults`.
@@ -78,8 +79,8 @@ Get the current value for a given `key` in `NSUserDefaults`.
### `set()`
-```jsx
-static set(settings: object)
+```tsx
+static set(settings: Record);
```
Set one or more values in `NSUserDefaults`.
@@ -88,8 +89,8 @@ Set one or more values in `NSUserDefaults`.
### `watchKeys()`
-```jsx
-static watchKeys(keys: string | array, callback: function): number
+```tsx
+static watchKeys(keys: string | array, callback: () => void): number;
```
Subscribe to be notified when the value for any of the keys specified by the `keys` parameter has been changed in `NSUserDefaults`. Returns a `watchId` number that may be used with `clearWatch()` to unsubscribe.
diff --git a/docs/shadow-props.md b/docs/shadow-props.md
index b46e2f74f8c..50f9e18d182 100644
--- a/docs/shadow-props.md
+++ b/docs/shadow-props.md
@@ -3,11 +3,16 @@ id: shadow-props
title: Shadow Props
---
-```SnackPlayer name=Shadow%20Props&supportedPlatforms=ios
-import React, { useState } from "react";
-import { Text, View, StyleSheet, Slider } from "react-native";
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
-const ShadowPropSlider = ({ label, value, ...props }) => {
+
+
+
+```SnackPlayer name=Shadow%20Props&supportedPlatforms=ios&ext=js
+import React, {useState} from 'react';
+import {Text, View, StyleSheet, Slider} from 'react-native';
+
+const ShadowPropSlider = ({label, value, ...props}) => {
return (
<>
@@ -16,7 +21,7 @@ const ShadowPropSlider = ({ label, value, ...props }) => {
>
);
-}
+};
const App = () => {
const [shadowOffsetWidth, setShadowOffsetWidth] = useState(0);
@@ -32,11 +37,11 @@ const App = () => {
{
shadowOffset: {
width: shadowOffsetWidth,
- height: -shadowOffsetHeight
+ height: -shadowOffsetHeight,
},
shadowOpacity,
- shadowRadius
- }
+ shadowRadius,
+ },
]}
/>
@@ -45,21 +50,21 @@ const App = () => {
minimumValue={-50}
maximumValue={50}
value={shadowOffsetWidth}
- onValueChange={val => setShadowOffsetWidth(val)}
+ onValueChange={setShadowOffsetWidth}
/>
setShadowOffsetHeight(val)}
+ onValueChange={setShadowOffsetHeight}
/>
setShadowRadius(val)}
+ onValueChange={setShadowRadius}
/>
{
);
-}
+};
const styles = StyleSheet.create({
container: {
flex: 1,
- justifyContent: "space-around",
- backgroundColor: "#ecf0f1",
- padding: 8
+ justifyContent: 'space-around',
+ backgroundColor: '#ecf0f1',
+ padding: 8,
},
square: {
- alignSelf: "center",
- backgroundColor: "white",
+ alignSelf: 'center',
+ backgroundColor: 'white',
borderRadius: 4,
height: 150,
- shadowColor: "black",
- width: 150
+ shadowColor: 'black',
+ width: 150,
},
controls: {
- paddingHorizontal: 12
- }
+ paddingHorizontal: 12,
+ },
});
export default App;
```
+
+
+
+```SnackPlayer name=Shadow%20Props&supportedPlatforms=ios&ext=tsx
+import React, {useState} from 'react';
+import {Text, View, StyleSheet, Slider} from 'react-native';
+import type {SliderProps} from 'react-native';
+
+type ShadowPropSliderProps = SliderProps & {
+ label: string;
+};
+
+const ShadowPropSlider = ({label, value, ...props}: ShadowPropSliderProps) => {
+ return (
+ <>
+
+ {label} ({value?.toFixed(2)})
+
+
+ >
+ );
+};
+
+const App = () => {
+ const [shadowOffsetWidth, setShadowOffsetWidth] = useState(0);
+ const [shadowOffsetHeight, setShadowOffsetHeight] = useState(0);
+ const [shadowRadius, setShadowRadius] = useState(0);
+ const [shadowOpacity, setShadowOpacity] = useState(0.1);
+
+ return (
+
+
+
+
+
+
+ setShadowOpacity(val)}
+ />
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'space-around',
+ backgroundColor: '#ecf0f1',
+ padding: 8,
+ },
+ square: {
+ alignSelf: 'center',
+ backgroundColor: 'white',
+ borderRadius: 4,
+ height: 150,
+ shadowColor: 'black',
+ width: 150,
+ },
+ controls: {
+ paddingHorizontal: 12,
+ },
+});
+
+export default App;
+```
+
+
+
+
# Reference
## Props
diff --git a/docs/share.md b/docs/share.md
index 0d1a2b38ff2..443beb7b70f 100644
--- a/docs/share.md
+++ b/docs/share.md
@@ -10,9 +10,12 @@ import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import con
-```SnackPlayer name=Function%20Component%20Example&supportedPlatforms=ios,android
+
+
+
+```SnackPlayer name=Function%20Component%20Example&supportedPlatforms=ios,android&ext=js
import React from 'react';
-import { Share, View, Button } from 'react-native';
+import {Alert, Share, View, Button} from 'react-native';
const ShareExample = () => {
const onShare = async () => {
@@ -31,11 +34,11 @@ const ShareExample = () => {
// dismissed
}
} catch (error) {
- alert(error.message);
+ Alert.alert(error.message);
}
};
return (
-
+
);
@@ -44,12 +47,55 @@ const ShareExample = () => {
export default ShareExample;
```
+
+
+
+```SnackPlayer name=Function%20Component%20Example&supportedPlatforms=ios,android&ext=tsx
+import React from 'react';
+import {Alert, Share, View, Button} from 'react-native';
+
+const ShareExample = () => {
+ const onShare = async () => {
+ try {
+ const result = await Share.share({
+ message:
+ 'React Native | A framework for building native apps using React',
+ });
+ if (result.action === Share.sharedAction) {
+ if (result.activityType) {
+ // shared with activity type of result.activityType
+ } else {
+ // shared
+ }
+ } else if (result.action === Share.dismissedAction) {
+ // dismissed
+ }
+ } catch (error: any) {
+ Alert.alert(error.message);
+ }
+ };
+ return (
+
+
+
+ );
+};
+
+export default ShareExample;
+```
+
+
+
+
-```SnackPlayer name=Class%20Component%20Example&supportedPlatforms=ios,android
-import React, { Component } from 'react';
-import { Share, View, Button } from 'react-native';
+
+
+
+```SnackPlayer name=Class%20Component%20Example&supportedPlatforms=ios,android&ext=js
+import React, {Component} from 'react';
+import {Alert, Share, View, Button} from 'react-native';
class ShareExample extends Component {
onShare = async () => {
@@ -69,13 +115,13 @@ class ShareExample extends Component {
// dismissed
}
} catch (error) {
- alert(error.message);
+ Alert.alert(error.message);
}
};
render() {
return (
-
+
);
@@ -85,6 +131,50 @@ class ShareExample extends Component {
export default ShareExample;
```
+
+
+
+```SnackPlayer name=Class%20Component%20Example&supportedPlatforms=ios,android&ext=tsx
+import React, {Component} from 'react';
+import {Alert, Share, View, Button} from 'react-native';
+
+class ShareExample extends Component {
+ onShare = async () => {
+ try {
+ const result = await Share.share({
+ message:
+ 'React Native | A framework for building native apps using React',
+ });
+
+ if (result.action === Share.sharedAction) {
+ if (result.activityType) {
+ // shared with activity type of result.activityType
+ } else {
+ // shared
+ }
+ } else if (result.action === Share.dismissedAction) {
+ // dismissed
+ }
+ } catch (error: any) {
+ Alert.alert(error.message);
+ }
+ };
+
+ render() {
+ return (
+
+
+
+ );
+ }
+}
+
+export default ShareExample;
+```
+
+
+
+
@@ -94,8 +184,8 @@ export default ShareExample;
### `share()`
-```jsx
-static share(content, options)
+```tsx
+static share(content: ShareContent, options?: ShareOptions);
```
Open a dialog to share text content.
@@ -106,10 +196,10 @@ In Android, returns a Promise which will always be resolved with action being `S
**Properties:**
-| Name | Type | Description |
-| ------------------------------------------------------------ | ------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| content
Required
| object | `message` - a message to share `url` - a URL to share
iOS
`title` - title of the message
Android
At least one of `url` and `message` is required. |
-| options | object | `dialogTitle`
Android
`excludedActivityTypes`
iOS
`subject` - a subject to share via email
iOS
`tintColor`
iOS
|
+| Name | Type | Description |
+| ------------------------------------------------------------ | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| content
Required
| object | `message` - a message to share `url` - a URL to share
iOS
`title` - title of the message
Android
At least one of `url` and `message` is required. |
+| options | object | `dialogTitle`
Android
`excludedActivityTypes`
iOS
`subject` - a subject to share via email
iOS
`tintColor`
iOS
`anchor` - the node to which the action sheet should be anchored (used for iPad)
iOS
|
---
@@ -117,8 +207,8 @@ In Android, returns a Promise which will always be resolved with action being `S
### `sharedAction`
-```jsx
-static sharedAction
+```tsx
+static sharedAction: 'sharedAction';
```
The content was successfully shared.
@@ -127,8 +217,8 @@ The content was successfully shared.
### `dismissedAction`
iOS
-```jsx
-static dismissedAction
+```tsx
+static dismissedAction: 'dismissedAction';
```
The dialog has been dismissed.
diff --git a/docs/state.md b/docs/state.md
index 85dd5086f07..ba3aeaf578e 100644
--- a/docs/state.md
+++ b/docs/state.md
@@ -3,48 +3,99 @@ id: state
title: State
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
There are two types of data that control a component: `props` and `state`. `props` are set by the parent and they are fixed throughout the lifetime of a component. For data that is going to change, we have to use `state`.
In general, you should initialize `state` in the constructor, and then call `setState` when you want to change it.
For example, let's say we want to make text that blinks all the time. The text itself gets set once when the blinking component gets created, so the text itself is a `prop`. The "whether the text is currently on or off" changes over time, so that should be kept in `state`.
-```SnackPlayer name=State
-import React, { useState, useEffect } from 'react';
-import { Text, View } from 'react-native';
+
+
+
+```SnackPlayer name=State&ext=js
+import React, {useState, useEffect} from 'react';
+import {Text, View} from 'react-native';
-const Blink = (props) => {
+const Blink = props => {
const [isShowingText, setIsShowingText] = useState(true);
- useEffect(() => {
- const toggle = setInterval(() => {
- setIsShowingText(!isShowingText);
- }, 1000);
+ useEffect(() => {
+ const toggle = setInterval(() => {
+ setIsShowingText(!isShowingText);
+ }, 1000);
- return () => clearInterval(toggle);
- })
+ return () => clearInterval(toggle);
+ });
if (!isShowingText) {
return null;
}
return {props.text};
-}
+};
const BlinkApp = () => {
return (
-
-
-
-
+
+
+
+
);
-}
+};
export default BlinkApp;
```
+
+
+
+```SnackPlayer name=State&ext=tsx
+import React, {useState, useEffect} from 'react';
+import {Text, View} from 'react-native';
+
+type BlinkProps = {
+ text: string;
+};
+
+const Blink = (props: BlinkProps) => {
+ const [isShowingText, setIsShowingText] = useState(true);
+
+ useEffect(() => {
+ const toggle = setInterval(() => {
+ setIsShowingText(!isShowingText);
+ }, 1000);
+
+ return () => clearInterval(toggle);
+ });
+
+ if (!isShowingText) {
+ return null;
+ }
+
+ return {props.text};
+};
+
+const BlinkApp = () => {
+ return (
+
+
+
+
+
+
+ );
+};
+
+export default BlinkApp;
+```
+
+
+
+
In a real application, you probably won't be setting state with a timer. You might set state when you have new data from the server, or from user input. You can also use a state container like [Redux](https://redux.js.org/) or [MobX](https://mobx.js.org/) to control your data flow. In that case you would use Redux or MobX to modify your state rather than calling `setState` directly.
When setState is called, BlinkApp will re-render its Component. By calling setState within the Timer, the component will re-render every time the Timer ticks.
diff --git a/docs/statusbar.md b/docs/statusbar.md
index 86208cdb4d6..41c2e694bcf 100644
--- a/docs/statusbar.md
+++ b/docs/statusbar.md
@@ -3,15 +3,28 @@ id: statusbar
title: StatusBar
---
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
Component to control the app's status bar. The status bar is the zone, typically at the top of the screen, that displays the current time, Wi-Fi and cellular network information, battery level and/or other status icons.
### Usage with Navigator
It is possible to have multiple `StatusBar` components mounted at the same time. The props will be merged in the order the `StatusBar` components were mounted.
-```SnackPlayer name=StatusBar%20Component%20Example&supportedPlatforms=android,ios
-import React, { useState } from 'react';
-import { Button, Platform, SafeAreaView, StatusBar, StyleSheet, Text, View } from 'react-native';
+
+
+
+```SnackPlayer name=StatusBar%20Component%20Example&supportedPlatforms=android,ios&ext=js
+import React, {useState} from 'react';
+import {
+ Button,
+ Platform,
+ SafeAreaView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
const STYLES = ['default', 'dark-content', 'light-content'];
const TRANSITIONS = ['fade', 'slide', 'none'];
@@ -19,7 +32,9 @@ const TRANSITIONS = ['fade', 'slide', 'none'];
const App = () => {
const [hidden, setHidden] = useState(false);
const [statusBarStyle, setStatusBarStyle] = useState(STYLES[0]);
- const [statusBarTransition, setStatusBarTransition] = useState(TRANSITIONS[0]);
+ const [statusBarTransition, setStatusBarTransition] = useState(
+ TRANSITIONS[0],
+ );
const changeStatusBarVisibility = () => setHidden(!hidden);
@@ -48,7 +63,8 @@ const App = () => {
backgroundColor="#61dafb"
barStyle={statusBarStyle}
showHideTransition={statusBarTransition}
- hidden={hidden} />
+ hidden={hidden}
+ />
StatusBar Visibility:{'\n'}
{hidden ? 'Hidden' : 'Visible'}
@@ -64,16 +80,13 @@ const App = () => {
) : null}
-
-
+
+
{Platform.OS === 'ios' ? (
+ onPress={changeStatusBarTransition}
+ />
) : null}
@@ -84,20 +97,126 @@ const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
- backgroundColor: '#ECF0F1'
+ backgroundColor: '#ECF0F1',
},
buttonsContainer: {
- padding: 10
+ padding: 10,
},
textStyle: {
textAlign: 'center',
- marginBottom: 8
- }
+ marginBottom: 8,
+ },
});
export default App;
```
+
+
+
+```SnackPlayer name=StatusBar%20Component%20Example&supportedPlatforms=android,ios&ext=tsx
+import React, {useState} from 'react';
+import {
+ Button,
+ Platform,
+ SafeAreaView,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+import type {StatusBarStyle} from 'react-native';
+
+const STYLES = ['default', 'dark-content', 'light-content'] as const;
+const TRANSITIONS = ['fade', 'slide', 'none'] as const;
+
+const App = () => {
+ const [hidden, setHidden] = useState(false);
+ const [statusBarStyle, setStatusBarStyle] = useState(
+ STYLES[0],
+ );
+ const [statusBarTransition, setStatusBarTransition] = useState<
+ 'fade' | 'slide' | 'none'
+ >(TRANSITIONS[0]);
+
+ const changeStatusBarVisibility = () => setHidden(!hidden);
+
+ const changeStatusBarStyle = () => {
+ const styleId = STYLES.indexOf(statusBarStyle) + 1;
+ if (styleId === STYLES.length) {
+ setStatusBarStyle(STYLES[0]);
+ } else {
+ setStatusBarStyle(STYLES[styleId]);
+ }
+ };
+
+ const changeStatusBarTransition = () => {
+ const transition = TRANSITIONS.indexOf(statusBarTransition) + 1;
+ if (transition === TRANSITIONS.length) {
+ setStatusBarTransition(TRANSITIONS[0]);
+ } else {
+ setStatusBarTransition(TRANSITIONS[transition]);
+ }
+ };
+
+ return (
+
+
+
+ StatusBar Visibility:{'\n'}
+ {hidden ? 'Hidden' : 'Visible'}
+
+
+ StatusBar Style:{'\n'}
+ {statusBarStyle}
+
+ {Platform.OS === 'ios' ? (
+
+ StatusBar Transition:{'\n'}
+ {statusBarTransition}
+
+ ) : null}
+
+
+
+ {Platform.OS === 'ios' ? (
+
+ ) : null}
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ backgroundColor: '#ECF0F1',
+ },
+ buttonsContainer: {
+ padding: 10,
+ },
+ textStyle: {
+ textAlign: 'center',
+ marginBottom: 8,
+ },
+});
+
+export default App;
+```
+
+
+
+
### Imperative API
For cases where using a component is not ideal, there is also an imperative API exposed as static functions on the component. It is however not recommended to use the static API and the component for the same prop because any value set by the static API will get overridden by the one set by the component in the next render.
@@ -190,8 +309,8 @@ If the status bar is translucent. When translucent is set to `true`, the app wil
### `popStackEntry()`
-```jsx
-static popStackEntry(entry: any)
+```tsx
+static popStackEntry(entry: StatusBarProps);
```
Get and remove the last StatusBar entry from the stack.
@@ -206,8 +325,8 @@ Get and remove the last StatusBar entry from the stack.
### `pushStackEntry()`
-```jsx
-static pushStackEntry(props: any)
+```tsx
+static pushStackEntry(props: StatusBarProps): StatusBarProps;
```
Push a StatusBar entry onto the stack. The return value should be passed to `popStackEntry` when complete.
@@ -222,8 +341,11 @@ Push a StatusBar entry onto the stack. The return value should be passed to `pop
### `replaceStackEntry()`
-```jsx
-static replaceStackEntry(entry: any, props: any)
+```tsx
+static replaceStackEntry(
+ entry: StatusBarProps,
+ props: StatusBarProps
+): StatusBarProps;
```
Replace an existing StatusBar stack entry with new props.
@@ -239,8 +361,8 @@ Replace an existing StatusBar stack entry with new props.
### `setBackgroundColor()`
Android
-```jsx
-static setBackgroundColor(color: string, [animated]: boolean)
+```tsx
+static setBackgroundColor(color: ColorValue, animated?: boolean);
```
Set the background color for the status bar.
@@ -256,8 +378,8 @@ Set the background color for the status bar.
### `setBarStyle()`
-```jsx
-static setBarStyle(style: StatusBarStyle, [animated]: boolean)
+```tsx
+static setBarStyle(style: StatusBarStyle, animated?: boolean);
```
Set the status bar style.
@@ -273,8 +395,8 @@ Set the status bar style.
### `setHidden()`
-```jsx
-static setHidden(hidden: boolean, [animation]: StatusBarAnimation)
+```tsx
+static setHidden(hidden: boolean, animation?: StatusBarAnimation);
```
Show or hide the status bar.
@@ -290,8 +412,8 @@ Show or hide the status bar.
### `setNetworkActivityIndicatorVisible()`
iOS
-```jsx
-static setNetworkActivityIndicatorVisible(visible: boolean)
+```tsx
+static setNetworkActivityIndicatorVisible(visible: boolean);
```
Control the visibility of the network activity indicator.
@@ -306,8 +428,8 @@ Control the visibility of the network activity indicator.
### `setTranslucent()`
Android
-```jsx
-static setTranslucent(translucent: boolean)
+```tsx
+static setTranslucent(translucent: boolean);
```
Control the translucency of the status bar.
diff --git a/docs/style.md b/docs/style.md
index 97f27400d2b..d847c0597cb 100644
--- a/docs/style.md
+++ b/docs/style.md
@@ -11,17 +11,17 @@ As a component grows in complexity, it is often cleaner to use `StyleSheet.creat
```SnackPlayer name=Style
import React from 'react';
-import { StyleSheet, Text, View } from 'react-native';
+import {StyleSheet, Text, View} from 'react-native';
const LotsOfStyles = () => {
- return (
-
- just red
- just bigBlue
- bigBlue, then red
- red, then bigBlue
-
- );
+ return (
+
+ just red
+ just bigBlue
+ bigBlue, then red
+ red, then bigBlue
+
+ );
};
const styles = StyleSheet.create({
diff --git a/docs/stylesheet.md b/docs/stylesheet.md
index 22910135f61..a4872a50f45 100644
--- a/docs/stylesheet.md
+++ b/docs/stylesheet.md
@@ -6,8 +6,8 @@ title: StyleSheet
A StyleSheet is an abstraction similar to CSS StyleSheets
```SnackPlayer name=StyleSheet
-import React from "react";
-import { StyleSheet, Text, View } from "react-native";
+import React from 'react';
+import {StyleSheet, Text, View} from 'react-native';
const App = () => (
@@ -19,20 +19,20 @@ const styles = StyleSheet.create({
container: {
flex: 1,
padding: 24,
- backgroundColor: "#eaeaea"
+ backgroundColor: '#eaeaea',
},
title: {
marginTop: 16,
paddingVertical: 8,
borderWidth: 4,
- borderColor: "#20232a",
+ borderColor: '#20232a',
borderRadius: 6,
- backgroundColor: "#61dafb",
- color: "#20232a",
- textAlign: "center",
+ backgroundColor: '#61dafb',
+ color: '#20232a',
+ textAlign: 'center',
fontSize: 30,
- fontWeight: "bold"
- }
+ fontWeight: 'bold',
+ },
});
export default App;
@@ -51,15 +51,15 @@ Code quality tips:
### `compose()`
-```jsx
-static compose(style1: object, style2: object): object | array