` | `` | 显示、样式和嵌套文本字符串,甚至处理触摸事件 |
+| `` | `` | `` | ` ` | 显示不同类型的图片 |
+| `` | `` | `` | `` | 一个通用的滚动容器,可以包含多个组件和视图 |
+| `
` | `` | `` | ` ` | 使用户可以输入文本 |
+
+在接下来的章节,您将开始组合这些核心组件,来了解 React 的工作方式。先做一些热身吧!
+
+```SnackPlayer name=Hello%20World
+import React from 'react';
+import { View, Text, Image, ScrollView, TextInput } from 'react-native';
+
+const App = () => {
+ return (
+
+ Some text
+
+ Some more text
+
+
+
+
+ );
+}
+
+export default App;
+```
+
+---
+
+由于 React Native 使用与 React 组件相同的 API 结构,因此您需要了解 React 组件 API 才能上手。您可以在[下一章节学习](intro-react)到关于此的简单介绍或复习相关内容。如果您已经熟悉 React,请您[随时跳过](handling-text-input)。
+
+
diff --git a/cnwebsite/versioned_docs/version-0.85/intro-react.md b/cnwebsite/versioned_docs/version-0.85/intro-react.md
new file mode 100644
index 00000000000..2a1f2ce7dc7
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/intro-react.md
@@ -0,0 +1,538 @@
+---
+id: intro-react
+title: React 基础
+description: 要深入理解 React Native,需要扎实的React 基础知识。这篇小教程可以帮助你入门或者温习相关知识。
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+React Native 的基础是[React](https://zh-hans.reactjs.org/), 是在 web 端非常流行的开源 UI 框架。要想掌握 React Native,先了解 React 框架本身是非常有帮助的。本文旨在为初学者介绍一些 react 的入门知识。
+
+本文主要会探讨以下几个 React 的核心概念:
+
+- components 组件
+- JSX
+- props 属性
+- state 状态
+
+如果你想更深一步学习,我们建议你阅读[React 的官方文档](https://zh-hans.reactjs.org/),它也提供有中文版。
+
+## 尝试编写一个组件
+
+本文档会用“Cat”这种有个名字和咖啡馆就能开始工作的人畜无害的生物来作为例子。下面是我们的第一个 Cat 组件:
+
+
+
+
+```SnackPlayer name=Your%20Cat
+import React from 'react';
+import { Text } from 'react-native';
+
+const Cat = () => {
+ return (
+ Hello, I am your cat!
+ );
+}
+
+export default Cat;
+```
+
+要定义一个`Cat`组件,第一步要使用[`import`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import)语句来引入`React`以及`React Native`的[`Text`](text)组件:
+
+```jsx
+import React from 'react';
+import {Text} from 'react-native';
+```
+
+然后一个简单的函数就可以作为一个组件:
+
+```jsx
+const Cat = () => {};
+```
+
+这个函数的`返回值`就会被渲染为一个 React 元素。这里`Cat`会渲染一个``元素:
+
+```jsx
+const Cat = () => {
+ return Hello, I am your cat! ;
+};
+```
+
+这里我们还使用了[`export default`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export)语句来导出这个组件,以使其可以在其他地方引入使用:
+
+```jsx
+const Cat = () => {
+ return Hello, I am your cat! ;
+};
+
+export default Cat;
+```
+
+
+
+
+Class 组件比函数组件写起来要繁琐一些。
+
+```SnackPlayer name=Your%20Cat
+import React, { Component } from 'react';
+import { Text } from 'react-native';
+
+class Cat extends Component {
+ render() {
+ return (
+ Hello, I am your cat!
+ );
+ }
+}
+
+export default Cat;
+```
+
+你还需要从 React 中引入`Component`:
+
+```jsx
+import React, {Component} from 'react';
+```
+
+定义组件首先要继承(extends)自`Component`:
+
+```jsx
+class Cat extends Component {}
+```
+
+Class 组件必须有一个`render()`函数,它的返回值会被渲染为一个 React 元素:
+
+```jsx
+class Cat extends Component {
+ render() {
+ return Hello, I am your cat! ;
+ }
+}
+```
+
+和函数组件一样,我们也可以导出 class 组件:
+
+```jsx
+class Cat extends Component {
+ render() {
+ return Hello, I am your cat! ;
+ }
+}
+
+export default Cat;
+```
+
+
+
+
+> 上面只是导出组件的写法之一。你还可以看看这篇博客整理[handy cheatsheet on JavaScript imports and exports](https://www.samanthaming.com/tidbits/79-module-cheatsheet/)整理的各种不同的写法。
+
+下面我们来看看这个`return` 语句。`Hello, I am your cat! `是一种简化 React 元素的写法,这种语法名字叫做 JSX。
+
+## JSX
+
+React 和 React Native 都使用**JSX 语法**,这种语法使得你可以在 JavaScript 中直接输出元素:`Hello, I am your cat! `。React 的文档有一份完整的[JSX 指南](https://zh-hans.reactjs.org/docs/jsx-in-depth.html#gatsby-focus-wrapper)可供你参考。因为 JSX 本质上也就是 JavaScript,所以你可以在其中直接使用变量。这里我们为猫猫的名字声明了一个变量`name`,并且用括号把它放在了``之中。
+
+```SnackPlayer name=Curly%20Braces
+import React from 'react';
+import { Text } from 'react-native';
+
+const Cat = () => {
+ const name = "Maru";
+ return (
+ Hello, I am {name}!
+ );
+}
+
+export default Cat;
+```
+
+``
+
+括号中可以使用任意 JavaScript 表达式,包括调用函数,例如`{getFullName("Rum", Tum", "Tugger")}`:
+
+```SnackPlayer name=Curly%20Braces
+import React from 'react';
+import { Text } from 'react-native';
+
+const getFullName = (firstName, secondName, thirdName) => {
+ return firstName + " " + secondName + " " + thirdName;
+}
+
+const Cat = () => {
+ return (
+
+ Hello, I am {getFullName("Rum", "Tum", "Tugger")}!
+
+ );
+}
+
+export default Cat;
+```
+
+你可以把括号`{}`想象成在 JSX 中打开了一个可以调用 JS 功能的传送门!
+
+> 在 React Native 0.71 版本之前,JSX 语法糖的实质是调用`React.createElement`方法,所以你必须在文件头部引用`import React from 'react'`。但在 React Native 0.71 版本之后,官方引入了[新的 JSX 转换](https://zh-hans.reactjs.org/blog/2020/09/22/introducing-the-new-jsx-transform.html),可以**不用**再在文件头部写`import React from 'react'`。
+
+## 自定义组件
+
+你应该已经了解[React Native 的核心组件](intro-react-native-components)了。 React 使得你可以通过嵌套这些组件来创造新组件。这些可嵌套可复用的组件正是 React 理念的精髓。
+
+例如你可以把[`Text`](text)和[`TextInput`](textinput)嵌入到[`View`](view) 中,React Native 会把它们一起渲染出来:
+
+```SnackPlayer name=Custom%20Components
+import React from 'react';
+import { Text, TextInput, View } from 'react-native';
+
+const Cat = () => {
+ return (
+
+ Hello, I am...
+
+
+ );
+}
+
+export default Cat;
+```
+
+#### 对开发者的提示
+
+
+
+
+
+> 如果你熟悉 web 开发,``和``应该能让你想起 HTML。你可以把它们看作是应用开发中的``和`
`标签。
+
+
+
+
+> 在 Android 上,常见的做法是把视图放入`LinearLayout`, `FrameLayout`或是`RelativeLayout`等布局容器中来定义子元素如何排列。在 React Native 中, `View` 使用弹性盒模型(Flexbox)来为子元素布局。详情请参考[使用 Flexbox 布局](flexbox)。
+
+
+
+
+这样你就可以在别处通过``来任意引用这个组件了:
+
+```SnackPlayer name=Multiple%20Components
+import React from 'react';
+import { Text, TextInput, View } from 'react-native';
+
+const Cat = () => {
+ return (
+
+ I am also a cat!
+
+ );
+}
+
+const Cafe = () => {
+ return (
+
+ Welcome!
+
+
+
+
+ );
+}
+
+export default Cafe;
+```
+
+我们把包含着其他组件的组件称为**父组件或父容器**。这里`Cafe`是一个父组件,而每个`Cat`则是**子组件**。
+
+你的咖啡店里,想养多少只猫都行!注意每只``渲染的都是不同的元素——你可以使用不同的 props 属性来定制它们。
+
+## Props 属性
+
+**Props** 是“properties”(属性)的简写。Props 使得我们可以定制组件。比如可以给每只``一个不同的`name`:
+
+```SnackPlayer name=Multiple%20Props
+import React from 'react';
+import { Text, View } from 'react-native';
+
+const Cat = (props) => {
+ return (
+
+ Hello, I am {props.name}!
+
+ );
+}
+
+const Cafe = () => {
+ return (
+
+
+
+
+
+ );
+}
+
+export default Cafe;
+```
+
+React Native 的绝大多数核心组件都提供了可定制的 props。例如,在使用[`Image`](image)组件时,你可以给它传递一个[`source`](image#source)属性,用来指定它显示的内容:
+
+```SnackPlayer name=Props
+import React from 'react';
+import { Text, View, Image } from 'react-native';
+
+const CatApp = () => {
+ return (
+
+
+ Hello, I am your cat!
+
+ );
+}
+
+export default CatApp;
+```
+
+`Image` 有[很多不同的 props](image#props),[`style`](image#style)也是其中之一,它接受对象形式的样式和布局键值对。
+
+> 请留意我们在指定`style`属性的宽高时所用到的双层括号`{{ }}`。在 JSX 中,引用 JS 值时需要使用`{}`括起来。在你需要传递非字符串值(比如数组或者数字)的时候会经常用到这种写法:` age={2}`。然而我们在 JS 中定义一个对象时,本来***也***需要用括号括起来:`{width: 200, height: 200}`。因此要在 JSX 中传递一个 JS 对象值的时候,就必须用到两层括号:`{{width: 200, height: 200}}`。
+
+使用核心组件[`Text`](text), [`Image`](image)以及[`View`](view)搭配 props 已经可以做不少东西了!但是如果想要做一些用户交互,那我们还需要用到状态(state)。
+
+## State 状态
+
+如果把 props 理解为定制组件渲染的参数, 那么**state**就像是组件的私人数据记录。状态用于记录那些随时间或者用户交互而变化的数据。状态使组件拥有了记忆!
+
+> 按惯例来说,props 用来配置组件的第一次渲染(初始状态)。state 则用来记录组件中任意可能随时间变化的数据。下面示例的情景发生在一个猫咪咖啡馆中,两只猫咪正嗷嗷待哺。它们的饥饿程度会随着时间变化(相对地,它们的名字就不会变化),因此会记录在状态中。示例中还有一个喂食按钮,一键干饭,扫除饥饿状态!
+
+
+
+
+你可以使用[React 的`useState` Hook](https://zh-hans.reactjs.org/docs/hooks-state.html)来为组件添加状态。Hook (钩子)是一种特殊的函数,可以让你“钩住”一些 React 的特性。例如`useState`可以在函数组件中添加一个“状态钩子”,在函数组件重新渲染执行的时候能够保持住之前的状态。要了解更多,可以阅读[React 中有关 Hook 的文档](https://zh-hans.reactjs.org/docs/hooks-intro.html)。
+
+```SnackPlayer name=State
+import React, { useState } from "react";
+import { Button, Text, View } from "react-native";
+
+const Cat = (props) => {
+ 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;
+```
+
+首先要从 react 中引入`useState`:
+
+```jsx
+import React, {useState} from 'react';
+```
+
+然后可以通过在函数内调用`useState`来为组件声明状态。在本示例中 `useState` 创建了一个 `isHungry` 状态变量:
+
+```jsx
+const Cat = props => {
+ const [isHungry, setIsHungry] = useState(true);
+ // ...
+};
+```
+
+> 你可以使用`useState`来记录各种类型的数据: strings, numbers, Booleans, arrays, objects。例如你可以这样来记录猫咪被爱抚的次数:`const [timesPetted, setTimesPetted] = useState(0)`。`useState`实质上做了两件事情:
+
+- 创建一个“状态变量”,并赋予一个初始值。上面例子中的状态变量是`isHungry`,初始值为`true`。
+- 同时创建一个函数用于设置此状态变量的值——`setIsHungry`。
+
+取什么名字并不重要。但脑海中应该形成这样一种模式:`[<取值>, <设值>] = useState(<初始值>)`.
+
+下面我们添加一个按钮[`Button`](button)组件,并给它一个`onPress`的 prop:
+
+```jsx
+ {
+ setIsHungry(false);
+ }}
+ //..
+/>
+```
+
+现在当用户点击按钮时,`onPress`函数会被触发,从而调用`setIsHungry(false)`。此时状态变量`isHungry`就被设为了`false`。当`isHungry`为 false 的时候,`Button`的`disabled`属性就变成了`true` ,其`title`也相应变化:
+
+```jsx
+
+```
+
+:::info
+你可能注意到虽然 `isHungry` 使用了常量关键字 [const](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Statements/const),但它看起来还是可以修改!这里的 `const` 并不意味着状态本身不可变,而是指"包含状态和更新函数"的引用不会改变。
+实际上,当你调用 `setIsHungry` 这样的状态设置函数时,其所在的组件会重新渲染。此处 `Cat` 函数会从头重新执行一遍——而这一次,`useState` 会返回给我们新的 `isHungry` 值。
+:::
+
+最后再把猫咪放进`Cafe`组件:
+
+```jsx
+const Cafe = () => {
+ return (
+ <>
+
+
+ >
+ );
+};
+```
+
+
+
+
+老式的 class 组件在使用 state 的写法上有所不同:
+
+```SnackPlayer name=State%20and%20Class%20Components
+import React, { Component } from "react";
+import { Button, Text, View } from "react-native";
+
+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;
+```
+
+再次强调,对于 class 组件始终要记得从 React 中引入`Component`:
+
+```jsx
+import React, {Component} from 'react';
+```
+
+在 class 组件中, state 以对象的形式存放:
+
+```jsx
+export class Cat extends Component {
+ state = {isHungry: true};
+ //..
+}
+```
+
+和使用`this.props`获取 props 一样,在组件中获取状态也是通过`this.state`:
+
+```jsx
+
+ I am {this.props.name}, and I am
+ {this.state.isHungry ? ' hungry' : ' full'}!
+
+```
+
+要修改状态中的值,只需给`this.setState()`传入一个对象,包含要修改的键值对即可:
+
+```jsx
+ {
+ this.setState({isHungry: false});
+ }}
+/>
+```
+
+> 不要直接给组件 state 赋值(比如`this.state.hunger = false`)来修改状态。使用 `this.setState()` 方法才能让 React 知悉状态的变化,从而触发重渲染。直接修改状态变量可能会使界面无法响应!
+
+当`this.state.isHungry`为 false 时,`Button`的`disabled`属性随之被设置为`false`,它的`title`也相应变化:
+
+```jsx
+
+```
+
+最后,把你的猫放到一个咖啡店`Cafe`组件中:
+
+```jsx
+class Cafe extends Component {
+ render() {
+ return (
+ <>
+
+
+ >
+ );
+ }
+}
+
+export default Cafe;
+```
+
+
+
+
+> 注意到上面的`<>`和`>`了吗? 这一对 JSX 标签称为[Fragments(片段)](https://zh-hans.reactjs.org/docs/fragments.html)。由于 JSX 的语法要求根元素必须为单个元素,如果我们需要在根节点处并列多个元素,在此前不得不额外套一个没有实际用处的`View`。但有了 Fragment 后就不需要引入额外的容器视图了。
+
+---
+
+现在你应该已经差不多了解 React 和 React Native 的核心组件与思想了。下面可以试着深入学习一些核心组件的用法,比如如何[处理文本输入``](handling-text-input)。
diff --git a/cnwebsite/versioned_docs/version-0.85/introduction.md b/cnwebsite/versioned_docs/version-0.85/introduction.md
new file mode 100644
index 00000000000..42b58fd8f4e
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/introduction.md
@@ -0,0 +1,93 @@
+---
+id: getting-started
+title: 简介
+description: 本指南将帮助你了解学习 React Native 的前置知识、如何使用本文档,以及如何搭建开发环境。
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+
+ 欢迎开启 React Native 学习之旅!如果你在寻找入门说明,它们已经移到了
单独的章节 。继续阅读,了解文档结构、原生组件、React 等内容!
+
+
+
+许多不同类型的人都在使用 React Native:从高级 iOS 开发者,到 React 初学者,再到职业生涯中第一次开始编程的人。这些文档是为所有学习者编写的,无论他们的经验水平或背景如何。
+
+## 如何使用本站文档
+
+你可以从这里开始,像看书一样线性阅读这些文档;也可以阅读你需要的特定部分。已经熟悉 React 了吗?你可以跳过[该部分](intro-react)--或者阅读它来进行简单的复习。
+
+## 预备知识
+
+要使用 React Native,你需要对 JavaScript 基础知识有所了解。如果你是 JavaScript 新手或需要复习,你可以在 MDN 上[深入学习](https://developer.mozilla.org/en-US/docs/Web/JavaScript)或[复习一下](https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript)。
+
+:::info
+虽然我们尽力假设你此前没有 React、Android 或 iOS 开发经验,但对于希望深入学习 React Native 的开发者来说,这些主题都很有价值。在合适的地方,我们也提供了更深入的参考资料和文章链接。
+:::
+
+## 交互示例
+
+本简介会通过像下面这样的交互示例,让你立刻在浏览器中上手:
+
+```SnackPlayer name=Hello%20World
+import React from 'react';
+import {Text, View} from 'react-native';
+
+const YourApp = () => {
+ return (
+
+ Try editing me! 🎉
+
+ );
+};
+
+export default YourApp;
+```
+
+上面的是一个 Snack Player。这是 Expo 提供的一个便捷工具,用来嵌入并运行 React Native 项目,并展示它们在 Android 和 iOS 等平台上的渲染效果。代码是实时可编辑的,因此你可以直接在浏览器中动手试试。现在就把上面的 “Try editing me!” 改成 “Hello, world!” 吧。
+
+:::tip
+如果你想在本地搭建开发环境,也可以按照我们的指南[在本机上配置开发环境](set-up-your-environment),然后把这些代码示例粘贴到你的项目中运行。(如果你是 Web 开发者,你可能已经为移动端浏览器调试配置好了本地环境!)
+:::
+
+## 开发者提示
+
+许多具有不同开发背景的人都在学习 React Native。你可能有各种技术经验,包括 Web、Android、iOS 等。我们尽量为不同背景的开发者编写文档。有时我们会像下面这样,针对某个平台提供特定说明:
+
+
+
+
+
+:::info
+Android 开发者可能会对这个概念比较熟悉。
+:::
+
+
+
+
+:::info
+iOS 开发者可能会对这个概念比较熟悉。
+:::
+
+
+
+
+:::info
+Web 开发者可能会对这个概念比较熟悉。
+:::
+
+
+
+
+## 特殊格式
+
+菜单路径会使用粗体书写,并使用尖括号分隔子菜单。例如:**Android Studio > Preferences**
+
+---
+
+现在你已经了解了本指南的使用方式,接下来该认识 React Native 的基础了:[原生组件](intro-react-native-components.md)。
diff --git a/cnwebsite/versioned_docs/version-0.85/javascript-environment.md b/cnwebsite/versioned_docs/version-0.85/javascript-environment.md
new file mode 100644
index 00000000000..d18794b0a68
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/javascript-environment.md
@@ -0,0 +1,109 @@
+---
+id: javascript-environment
+title: JavaScript 环境
+---
+
+import TableRow from '@site/core/TableRowWithCodeBlock';
+
+## JavaScript 运行时
+
+在使用 React Native 时,你的 JavaScript 代码最多会运行在三种环境中:
+
+- 在大多数情况下,React Native 会使用 [Hermes](hermes),这是一个为 React Native 优化的开源 JavaScript 引擎。
+- 如果禁用了 Hermes,React Native 会使用 [JavaScriptCore](https://trac.webkit.org/wiki/JavaScriptCore),也就是 Safari 所使用的 JavaScript 引擎。请注意,在 iOS 上,JavaScriptCore 不会使用 JIT,因为 iOS 应用中没有可写且可执行的内存。
+- 在使用 Chrome 调试时,所有 JavaScript 代码都会运行在 Chrome 本身中,并通过 WebSocket 与原生代码通信。Chrome 使用 [V8](https://v8.dev/) 作为其 JavaScript 引擎。
+
+虽然这些环境非常相似,但你最终还是可能会遇到一些不一致的情况。最好避免依赖任何特定运行时的细节。
+
+## JavaScript 语法转换器
+
+语法转换器可以使编写代码的过程更加享受,因为开发者可以借助转换器直接使用新的 JavaScript 语法标准,而无需等待 JS 解释器的支持。
+
+React Native 内置了 [Babel JavaScript 编译器](https://babeljs.io)。你可以查看 [Babel 文档](https://babeljs.io/docs/plugins/#transform-plugins) 了解它所支持的转换的更多细节。
+
+React Native 启用的完整转换列表可以在 [@react-native/babel-preset](https://github.com/facebook/react-native/tree/main/packages/react-native-babel-preset) 中找到。
+
+
+
+ Transformation Code
+
+
+ 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
+
+
+
+
+
+
+
+
+
+
+## 接口兼容(Polyfills)
+
+许多标准功能也都在支持的 JavaScript 运行环境上做了兼容支持。
+
+#### 浏览器
+
+- [CommonJS `require`](https://nodejs.org/docs/latest/api/modules.html)
+- `md [console.{log, warn, error, info, debug, trace, table, group, groupCollapsed, groupEnd}](https://developer.chrome.com/devtools/docs/console-api)`
+- [`XMLHttpRequest`, `fetch`](network.md#content)
+- [`{set, clear}{Timeout, Interval, Immediate}, {request, cancel}AnimationFrame`](timers.md#content)
+
+#### ECMAScript 2015 (ES6)
+
+- [`Array.from`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/from)
+- `md Array.prototype.{[find](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find), [findIndex](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/findIndex)}`
+- [`Object.assign`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign)
+- `md String.prototype.{[startsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith), [endsWith](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith), [repeat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat), [includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes)}`
+
+#### ECMAScript 2016 (ES7)
+
+- `md Array.prototype.[includes](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/includes)`
+
+#### ECMAScript 2017 (ES8)
+
+- `md Object.{[entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries), [values](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/values)}`
+
+#### 专有特性
+
+- `__DEV__` 用于判断当前是否开发环境的全局变量
diff --git a/cnwebsite/versioned_docs/version-0.85/keyboard.md b/cnwebsite/versioned_docs/version-0.85/keyboard.md
new file mode 100644
index 00000000000..d9d7941c61b
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/keyboard.md
@@ -0,0 +1,146 @@
+---
+id: keyboard
+title: Keyboard
+---
+
+`Keyboard`模块用来控制键盘相关的事件。
+
+### 用法示例
+
+`Keyboard`模块可以监听原生键盘事件以做出相应回应,比如收回键盘。
+
+```SnackPlayer name=Keyboard%20Example&supportedPlatforms=ios,android
+import React, {useState, useEffect} from 'react';
+import {Keyboard, Text, TextInput, StyleSheet} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const Example = () => {
+ const [keyboardStatus, setKeyboardStatus] = useState('Keyboard Hidden');
+
+ useEffect(() => {
+ const showSubscription = Keyboard.addListener('keyboardDidShow', () => {
+ setKeyboardStatus('Keyboard Shown');
+ });
+ const hideSubscription = Keyboard.addListener('keyboardDidHide', () => {
+ setKeyboardStatus('Keyboard Hidden');
+ });
+
+ return () => {
+ showSubscription.remove();
+ hideSubscription.remove();
+ };
+ }, []);
+
+ return (
+
+
+
+ {keyboardStatus}
+
+
+ );
+};
+
+const style = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 36,
+ },
+ input: {
+ padding: 10,
+ borderWidth: 0.5,
+ borderRadius: 4,
+ },
+ status: {
+ padding: 16,
+ textAlign: 'center',
+ },
+});
+
+export default Example;
+```
+
+---
+
+# 文档
+
+## 方法
+
+### `addListener()`
+
+```tsx
+static addListener: (
+ eventType: KeyboardEventName,
+ listener: KeyboardEventListener,
+) => EmitterSubscription;
+```
+
+`addListener`用于注册一个 JavaScript 函数来监听处理原生键盘通知事件。
+
+此方法会返回监听函数的引用。
+
+**参数:**
+
+| 名称 | 类型 | 说明 |
+| ------------------------------------------------------------------------ | -------- | ------------------------------------- |
+| eventName Required
| string | 用来指明要监听的事件,具体有以下几种: |
+| callback Required
| function | 事件触发时调用的 js 函数 |
+
+**`eventName`**
+
+事件为以下几种:
+
+- `keyboardWillShow`
+- `keyboardDidShow`
+- `keyboardWillHide`
+- `keyboardDidHide`
+- `keyboardWillChangeFrame`
+- `keyboardDidChangeFrame`
+
+:::note
+在 Android 上,只有 `keyboardDidShow` 和 `keyboardDidHide` 事件可用。如果你的 activity 将 `android:windowSoftInputMode` 设置为 `adjustResize` 或 `adjustNothing`,那么在 Android 10 及以下版本中,这些事件不会触发。
+:::
+
+---
+
+### `dismiss()`
+
+```tsx
+static dismiss()
+```
+
+把弹出的键盘收回去,同时使当前的文本框失去焦点。
+
+---
+
+### `scheduleLayoutAnimation`
+
+```tsx
+static scheduleLayoutAnimation(event: KeyboardEvent);
+```
+
+用于将 TextInput(或其他键盘附属视图)的大小或位置变化与键盘移动同步。
+
+---
+
+### `isVisible()`
+
+```tsx
+static isVisible(): boolean;
+```
+
+键盘当前是否弹出可见。
+
+---
+
+### `metrics()`
+
+```tsx
+static metrics(): KeyboardMetrics | undefined;
+```
+
+如果当前已经弹出软键盘,返回当前软键盘的尺寸。
diff --git a/cnwebsite/versioned_docs/version-0.85/keyboardavoidingview.md b/cnwebsite/versioned_docs/version-0.85/keyboardavoidingview.md
new file mode 100644
index 00000000000..a337556c522
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/keyboardavoidingview.md
@@ -0,0 +1,111 @@
+---
+id: keyboardavoidingview
+title: KeyboardAvoidingView
+---
+
+本组件用于解决一个常见的尴尬问题:手机上弹出的键盘常常会挡住当前的视图。本组件可以自动根据键盘的高度,调整自身的 height 或底部的 padding,以避免被遮挡。
+
+## 示例
+
+```SnackPlayer name=KeyboardAvoidingView&supportedPlatforms=android,ios
+import React from 'react';
+import { View, KeyboardAvoidingView, TextInput, StyleSheet, Text, Platform, TouchableWithoutFeedback, Button, Keyboard } from 'react-native';
+
+const KeyboardAvoidingComponent = () => {
+ return (
+
+
+
+ Header
+
+
+ null} />
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1
+ },
+ inner: {
+ padding: 24,
+ flex: 1,
+ justifyContent: "space-around"
+ },
+ header: {
+ fontSize: 36,
+ marginBottom: 48
+ },
+ textInput: {
+ height: 40,
+ borderColor: "#000000",
+ borderBottomWidth: 1,
+ marginBottom: 36
+ },
+ btnContainer: {
+ backgroundColor: "white",
+ marginTop: 12
+ }
+});
+
+export default KeyboardAvoidingComponent;
+```
+
+---
+
+# 文档
+
+## Props
+
+### [View Props](view.md#props)
+
+继承了所有的[View Props](view.md#props).
+
+---
+
+### `behavior`
+
+Specify how to react to the presence of the keyboard.
+
+> Android 和 iOS 在此属性上表现并不一致。但我们建议在两个平台上都明确设置此属性。
+
+| 类型 |
+| ------------------------------------------- |
+| enum(`'height'`, `'position'`, `'padding'`) |
+
+---
+
+### `contentContainerStyle`
+
+如果设定 behavior 值为`'position'`,则会生成一个 View 作为内容容器。此属性用于指定此内容容器的样式。
+
+| 类型 |
+| --------------------------------- |
+| [View Style](view-style-props.md) |
+
+---
+
+### `enabled`
+
+是否启用 KeyboardAvoidingView。
+
+| 类型 | 默认值 |
+| ------- | ------ |
+| boolean | `true` |
+
+---
+
+### `keyboardVerticalOffset`
+
+有时候应用离屏幕顶部还有一些距离(比如状态栏等等),利用此属性来补偿修正这段距离。
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| number | `0` |
diff --git a/cnwebsite/versioned_docs/version-0.85/layout-props.md b/cnwebsite/versioned_docs/version-0.85/layout-props.md
new file mode 100644
index 00000000000..29a3a528a16
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/layout-props.md
@@ -0,0 +1,1360 @@
+---
+id: layout-props
+title: 布局属性
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+:::info
+更多关于这些属性的详细示例可以在[Flexbox 布局](flexbox)页面上找到。
+:::
+
+### 示例
+
+以下示例展示了不同属性如何影响或塑造 React Native 布局。你可以尝试添加或删除 UI 中的方块,同时更改属性`flexWrap`的值来体验效果。
+
+
+
+
+```SnackPlayer name=LayoutProps%20Example&ext=js
+import React, {useState} from 'react';
+import {Button, ScrollView, StyleSheet, Text, View} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ 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 [squares, setSquares] = useState([ , , ]);
+
+ const hookedStyles = {
+ flexDirection: flexDirections[flexDirection],
+ justifyContent: justifyContents[justifyContent],
+ alignItems: alignItemsArr[alignItems],
+ direction: directions[direction],
+ flexWrap: wraps[wrap],
+ };
+
+ const changeSetting = (value, options, setterFunction) => {
+ if (value === options.length - 1) {
+ setterFunction(0);
+ return;
+ }
+ setterFunction(value + 1);
+ };
+
+ 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 flexDirections = ['row', 'row-reverse', 'column', 'column-reverse'];
+const justifyContents = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'space-between',
+ 'space-around',
+ 'space-evenly',
+];
+const alignItemsArr = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'stretch',
+ 'baseline',
+];
+const wraps = ['nowrap', 'wrap', 'wrap-reverse'];
+const directions = ['inherit', 'ltr', 'rtl'];
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ layoutContainer: {
+ flex: 0.5,
+ },
+ playingSpace: {
+ backgroundColor: 'white',
+ borderColor: 'blue',
+ borderWidth: 3,
+ overflow: 'hidden',
+ },
+ controlSpace: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ buttonView: {
+ width: '50%',
+ padding: 10,
+ },
+ text: {
+ textAlign: 'center',
+ },
+});
+
+const Square = () => (
+
+);
+
+const randomHexColor = () => {
+ return '#000000'.replace(/0/g, () => {
+ return Math.round(Math.random() * 14).toString(16);
+ });
+};
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=LayoutProps%20Example&ext=tsx
+import React, {useState} from 'react';
+import {
+ Button,
+ ScrollView,
+ StyleSheet,
+ Text,
+ View,
+ FlexAlignType,
+ FlexStyle,
+} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ 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 [squares, setSquares] = useState([ , , ]);
+
+ const hookedStyles = {
+ flexDirection: flexDirections[flexDirection],
+ justifyContent: justifyContents[justifyContent],
+ alignItems: alignItemsArr[alignItems],
+ direction: directions[direction],
+ flexWrap: wraps[wrap],
+ } as FlexStyle;
+
+ const changeSetting = (
+ value: number,
+ options: any[],
+ setterFunction: (index: number) => void,
+ ) => {
+ if (value === options.length - 1) {
+ setterFunction(0);
+ return;
+ }
+ setterFunction(value + 1);
+ };
+
+ 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 flexDirections = [
+ 'row',
+ 'row-reverse',
+ 'column',
+ 'column-reverse',
+] as FlexStyle['flexDirection'][];
+const justifyContents = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'space-between',
+ 'space-around',
+ 'space-evenly',
+] as FlexStyle['justifyContent'][];
+const alignItemsArr = [
+ 'flex-start',
+ 'flex-end',
+ 'center',
+ 'stretch',
+ 'baseline',
+] as FlexAlignType[];
+const wraps = ['nowrap', 'wrap', 'wrap-reverse'];
+const directions = ['inherit', 'ltr', 'rtl'];
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ layoutContainer: {
+ flex: 0.5,
+ },
+ playingSpace: {
+ backgroundColor: 'white',
+ borderColor: 'blue',
+ borderWidth: 3,
+ overflow: 'hidden',
+ },
+ controlSpace: {
+ flexDirection: 'row',
+ flexWrap: 'wrap',
+ },
+ buttonView: {
+ width: '50%',
+ padding: 10,
+ },
+ text: {
+ textAlign: 'center',
+ },
+});
+
+const Square = () => (
+
+);
+
+const randomHexColor = () => {
+ return '#000000'.replace(/0/g, () => {
+ return Math.round(Math.random() * 14).toString(16);
+ });
+};
+
+export default App;
+```
+
+
+
+
+---
+
+# Reference
+
+## Props
+
+### `alignContent`
+
+`alignContent` controls how rows align in the cross direction, overriding the `alignContent` of the parent.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/align-content) for more details.
+
+| Type | Required |
+| ---------------------------------------------------------------------------------------------------- | -------- |
+| enum('flex-start', 'flex-end', 'center', 'stretch', 'space-between', 'space-around', 'space-evenly') | No |
+
+---
+
+### `alignItems`
+
+`alignItems` aligns children in the cross direction. For example, if children are flowing vertically, `alignItems` controls how they align horizontally. It works like `align-items` in CSS (default: stretch).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/align-items) for more details.
+
+| Type | Required |
+| --------------------------------------------------------------- | -------- |
+| enum('flex-start', 'flex-end', 'center', 'stretch', 'baseline') | No |
+
+---
+
+### `alignSelf`
+
+`alignSelf` controls how a child aligns in the cross direction, overriding the `alignItems` of the parent. It works like `align-self` in CSS (default: auto).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/align-self) for more details.
+
+| Type | Required |
+| ----------------------------------------------------------------------- | -------- |
+| enum('auto', 'flex-start', 'flex-end', 'center', 'stretch', 'baseline') | No |
+
+---
+
+### `aspectRatio`
+
+Aspect ratio controls the size of the undefined dimension of a node.
+
+- On a node with a set width/height, aspect ratio controls the size of the unset dimension
+- On a node with a set flex basis, aspect ratio controls the size of the node in the cross axis if unset
+- On a node with a measure function, aspect ratio works as though the measure function measures the flex basis
+- On a node with flex grow/shrink, aspect ratio controls the size of the node in the cross axis if unset
+- Aspect ratio takes min/max dimensions into account
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `borderBottomWidth`
+
+`borderBottomWidth` works like `border-bottom-width` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/border-bottom-width) for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `borderEndWidth`
+
+When direction is `ltr`, `borderEndWidth` is equivalent to `borderRightWidth`. When direction is `rtl`, `borderEndWidth` is equivalent to `borderLeftWidth`.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `borderLeftWidth`
+
+`borderLeftWidth` works like `border-left-width` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/border-left-width) for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `borderRightWidth`
+
+`borderRightWidth` works like `border-right-width` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/border-right-width) for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `borderStartWidth`
+
+When direction is `ltr`, `borderStartWidth` is equivalent to `borderLeftWidth`. When direction is `rtl`, `borderStartWidth` is equivalent to `borderRightWidth`.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `borderTopWidth`
+
+`borderTopWidth` works like `border-top-width` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/border-top-width) for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `borderWidth`
+
+`borderWidth` works like `border-width` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/border-width) for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `bottom`
+
+`bottom` is the number of logical pixels to offset the bottom edge of this component.
+
+It works similarly to `bottom` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/bottom) for more details of how `bottom` affects layout.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `boxSizing`
+
+`boxSizing` defines how the element's various sizing props (`width`, `height`, `minWidth`, `minHeight`, etc.) are computed. If `boxSizing` is `border-box`, these sizes apply to the border box of the element. If it is `content-box`, they apply to the content box of the element. The default value is `border-box`. The [web documentation](https://developer.mozilla.org/en-US/docs/Web/CSS/box-sizing) is a good source of information if you wish to learn more about how this prop works.
+
+| Type | Required |
+| --------------------------------- | -------- |
+| enum('border-box', 'content-box') | No |
+
+---
+
+### `columnGap`
+
+`columnGap` works like `column-gap` in CSS. Only pixel units are supported in React Native.
+
+See [MDN CSS Reference](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 [MDN CSS Reference](https://www.yogalayout.dev/docs/styling/layout-direction) for more details.
+
+| Type | Required |
+| ----------------------------- | -------- |
+| enum('inherit', 'ltr', 'rtl') | No |
+
+---
+
+### `display`
+
+`display` sets the display type of this component.
+
+It works similarly to `display` in CSS but only supports the values 'flex', 'none', and 'contents'. The default is `flex`.
+
+| Type | Required |
+| -------------------------------- | -------- |
+| enum('none', 'flex', 'contents') | No |
+
+---
+
+### `end`
+
+When the direction is `ltr`, `end` is equivalent to `right`. When the direction is `rtl`, `end` is equivalent to `left`.
+
+This style takes precedence over the `left` and `right` styles.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `flex`
+
+In React Native `flex` does not work the same way that it does in CSS. `flex` is a number rather than a string, and it works according to the [Yoga](https://github.com/facebook/yoga) layout engine.
+
+When `flex` is a positive number, it makes the component flexible, and it will be sized proportional to its flex value. So a component with `flex` set to `2` will take twice the space as a component with `flex` set to 1. `flex: ` equates to `flexGrow: , flexShrink: 1, flexBasis: 0`.
+
+When `flex` is `0`, the component is sized according to `width` and `height`, and it is inflexible.
+
+When `flex` is `-1`, the component is normally sized according to `width` and `height`. However, if there's not enough space, the component will shrink to its `minWidth` and `minHeight`.
+
+`flexGrow`, `flexShrink`, and `flexBasis` work the same as in CSS.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `flexBasis`
+
+`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.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `flexDirection`
+
+`flexDirection` controls which directions children of a container go. `row` goes left to right, `column` goes top to bottom, and you may be able to guess what the other two do. It works like `flex-direction` in CSS, except the default is `column`.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-direction) for more details.
+
+| Type | Required |
+| ------------------------------------------------------ | -------- |
+| enum('row', 'row-reverse', 'column', 'column-reverse') | No |
+
+---
+
+### `flexGrow`
+
+`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.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `flexShrink`
+
+[`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. A container will shrink its children weighted by the children’s `flexShrink` values.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
+
+---
+
+### `flexWrap`
+
+`flexWrap` controls whether children can wrap around after they hit the end of a flex container. It works like `flex-wrap` in CSS (default: nowrap).
+
+Note it does not work anymore with `alignItems: stretch` (the default), so you may want to use `alignItems: flex-start` for example (breaking change details: https://github.com/facebook/react-native/releases/tag/v0.28.0).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/flex-wrap) for more details.
+
+| Type | Required |
+| -------------------------------------- | -------- |
+| enum('wrap', 'nowrap', 'wrap-reverse') | No |
+
+---
+
+### `gap`
+
+`gap` works like `gap` in CSS. Only pixel units are supported in React Native.
+
+See [MDN CSS Reference](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.
+
+It works similarly to `height` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/height) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `inset`
+
+:::note
+`inset` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+Setting `inset` has the same effect as setting each of `top`, `bottom`, `right` and `left` props.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/inset) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `insetBlock`
+
+:::note
+`insetBlock` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+Equivalent to [`top`](layout-props#top) and [`bottom`](layout-props#bottom).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `insetBlockEnd`
+
+:::note
+`insetBlockEnd` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+Equivalent to [`bottom`](layout-props#bottom).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block-end) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `insetBlockStart`
+
+:::note
+`insetBlockStart` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+Equivalent to [`top`](layout-props#top).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/inset-block-start) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `insetInline`
+
+:::note
+`insetInline` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+Equivalent to [`right`](layout-props#right) and [`left`](layout-props#left).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `insetInlineEnd`
+
+:::note
+`insetInlineEnd` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+When direction is `ltr`, `insetInlineEnd` is equivalent to [`right`](layout-props#right). When direction is `rtl`, `insetInlineEnd` is equivalent to [`left`](layout-props#left).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline-end) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `insetInlineStart`
+
+:::note
+`insetInlineStart` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+When direction is `ltr`, `insetInlineStart` is equivalent to [`left`](layout-props#left). When direction is `rtl`, `insetInlineStart` is equivalent to [`right`](layout-props#right).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/inset-inline-start) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `isolation`
+
+:::note
+`isolation` is only available on the [New Architecture](/architecture/landing-page)
+:::
+
+`isolation` lets you form a [stacking context](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_positioned_layout/Stacking_context).
+
+There are two values:
+
+- `auto` (default): Does nothing.
+- `isolate`: Forms a stacking context.
+
+| Type | Required |
+| ----------------------- | -------- |
+| enum('auto', 'isolate') | No |
+
+---
+
+### `justifyContent`
+
+`justifyContent` aligns children in the main direction. For example, if children are flowing vertically, `justifyContent` controls how they align vertically. It works like `justify-content` in CSS (default: flex-start).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/justify-content) for more details.
+
+| Type | Required |
+| ----------------------------------------------------------------------------------------- | -------- |
+| enum('flex-start', 'flex-end', 'center', 'space-between', 'space-around', 'space-evenly') | No |
+
+---
+
+### `left`
+
+`left` is the number of logical pixels to offset the left edge of this component.
+
+It works similarly to `left` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/left) for more details of how `left` affects layout.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `margin`
+
+Setting `margin` has the same effect as setting each of `marginTop`, `marginLeft`, `marginBottom`, and `marginRight`.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/margin) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginBottom`
+
+`marginBottom` works like `margin-bottom` in CSS. See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-bottom) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginBlock`
+
+Equivalent to [`marginVertical`](layout-props#marginvertical).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/margin-block) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginBlockEnd`
+
+Equivalent to [`marginBottom`](layout-props#marginbottom).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/margin-block-end) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginBlockStart`
+
+Equivalent to [`marginTop`](layout-props#margintop).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/margin-block-start) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginEnd`
+
+When direction is `ltr`, `marginEnd` is equivalent to `marginRight`. When direction is `rtl`, `marginEnd` is equivalent to `marginLeft`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginHorizontal`
+
+Setting `marginHorizontal` has the same effect as setting both `marginLeft` and `marginRight`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginInline`
+
+Equivalent to [`marginHorizontal`](layout-props#marginhorizontal).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/margin-inline) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginInlineEnd`
+
+When direction is `ltr`, `marginInlineEnd` is equivalent to [`marginEnd`](layout-props#marginend) (i.e. `marginRight`). When direction is `rtl`, `marginInlineEnd` is equivalent to [`marginEnd`](layout-props#marginend) (i.e. `marginLeft`).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/margin-inline-end) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginInlineStart`
+
+When direction is `ltr`, `marginInlineStart` is equivalent to [`marginStart`](layout-props#marginstart) (i.e. `marginLeft`). When direction is `rtl`, `marginInlineStart` is equivalent to [`marginStart`](layout-props#marginstart) (i.e. `marginRight`).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/margin-inline-start) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginLeft`
+
+`marginLeft` works like `margin-left` in CSS. See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-left) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginRight`
+
+`marginRight` works like `margin-right` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-right) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginStart`
+
+When direction is `ltr`, `marginStart` is equivalent to `marginLeft`. When direction is `rtl`, `marginStart` is equivalent to `marginRight`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginTop`
+
+`marginTop` works like `margin-top` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/margin-top) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `marginVertical`
+
+Setting `marginVertical` has the same effect as setting both `marginTop` and `marginBottom`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `maxHeight`
+
+`maxHeight` is the maximum height for this component, in logical pixels.
+
+It works similarly to `max-height` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/max-height) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `maxWidth`
+
+`maxWidth` is the maximum width for this component, in logical pixels.
+
+It works similarly to `max-width` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/max-width) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `minHeight`
+
+`minHeight` is the minimum height for this component, in logical pixels.
+
+It works similarly to `min-height` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/min-height) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `minWidth`
+
+`minWidth` is the minimum width for this component, in logical pixels.
+
+It works similarly to `min-width` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/min-width) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `overflow`
+
+`overflow` controls how children are measured and displayed. `overflow: hidden` causes views to be clipped while `overflow: scroll` causes views to be measured independently of their parents' main axis. It works like `overflow` in CSS (default: visible).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/overflow) for more details.
+
+| Type | Required |
+| ----------------------------------- | -------- |
+| enum('visible', 'hidden', 'scroll') | No |
+
+---
+
+### `padding`
+
+Setting `padding` has the same effect as setting each of `paddingTop`, `paddingBottom`, `paddingLeft`, and `paddingRight`.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/padding) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingBottom`
+
+`paddingBottom` works like `padding-bottom` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-bottom) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingBlock`
+
+Equivalent to [`paddingVertical`](layout-props#paddingvertical).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/padding-block) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingBlockEnd`
+
+Equivalent to [`paddingBottom`](layout-props#paddingbottom).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/padding-block-end) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingBlockStart`
+
+Equivalent to [`paddingTop`](layout-props#paddingtop).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/padding-block-start) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingEnd`
+
+When direction is `ltr`, `paddingEnd` is equivalent to `paddingRight`. When direction is `rtl`, `paddingEnd` is equivalent to `paddingLeft`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingHorizontal`
+
+Setting `paddingHorizontal` is like setting both of `paddingLeft` and `paddingRight`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingInline`
+
+Equivalent to [`paddingHorizontal`](layout-props#paddinghorizontal).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/padding-inline) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingInlineEnd`
+
+When direction is `ltr`, `paddingInlineEnd` is equivalent to [`paddingEnd`](layout-props#paddingend) (i.e. `paddingRight`). When direction is `rtl`, `paddingInlineEnd` is equivalent to [`paddingEnd`](layout-props#paddingend) (i.e. `paddingLeft`).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/padding-inline-end) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingInlineStart`
+
+When direction is `ltr`, `paddingInlineStart` is equivalent to [`paddingStart`](layout-props#paddingstart) (i.e. `paddingLeft`). When direction is `rtl`, `paddingInlineStart` is equivalent to [`paddingStart`](layout-props#paddingstart) (i.e. `paddingRight`).
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Properties/padding-inline-start) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingLeft`
+
+`paddingLeft` works like `padding-left` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-left) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingRight`
+
+`paddingRight` works like `padding-right` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-right) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingStart`
+
+When direction is `ltr`, `paddingStart` is equivalent to `paddingLeft`. When direction is `rtl`, `paddingStart` is equivalent to `paddingRight`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingTop`
+
+`paddingTop` works like `padding-top` in CSS.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/padding-top) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `paddingVertical`
+
+Setting `paddingVertical` is like setting both of `paddingTop` and `paddingBottom`.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `position`
+
+`position` in React Native is similar to [regular CSS](https://developer.mozilla.org/en-US/docs/Web/CSS/position), but everything is set to `relative` by default.
+
+`relative` will position an element according to the normal flow of the layout. Insets (`top`, `bottom`, `left`, `right`) will offset relative to this layout.
+
+`absolute` takes the element out of the normal flow of the layout. Insets will offset relative to its [containing block](./flexbox.md#the-containing-block).
+
+`static` will position an element according to the normal flow of the layout. Insets will have no effect.
+`static` elements do not form a containing block for absolute descendants.
+
+For more information, see the [Layout with Flexbox docs](./flexbox.md#position). Also, [the Yoga documentation](https://www.yogalayout.dev/docs/styling/position) has more details on how `position` differs between React Native and CSS.
+
+| Type | Required |
+| -------------------------------------- | -------- |
+| enum('absolute', 'relative', 'static') | No |
+
+---
+
+### `right`
+
+`right` is the number of logical pixels to offset the right edge of this component.
+
+It works similarly to `right` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/right) for more details of how `right` affects layout.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `rowGap`
+
+`rowGap` works like `row-gap` in CSS. Only pixel units are supported in React Native.
+
+See [MDN CSS Reference](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`.
+
+This style takes precedence over the `left`, `right`, and `end` styles.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `top`
+
+`top` is the number of logical pixels to offset the top edge of this component.
+
+It works similarly to `top` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/top) for more details of how `top` affects layout.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `width`
+
+`width` sets the width of this component.
+
+It works similarly to `width` in CSS, but in React Native you must use points or percentages. Ems and other units are not supported.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/width) for more details.
+
+| Type | Required |
+| -------------- | -------- |
+| number, string | No |
+
+---
+
+### `zIndex`
+
+`zIndex` controls which components display on top of others. Normally, you don't use `zIndex`. Components render according to their order in the document tree, so later components draw over earlier ones. `zIndex` may be useful if you have animations or custom modal interfaces where you don't want this behavior.
+
+It works like the CSS `z-index` property - components with a larger `zIndex` will render on top. Think of the z-direction like it's pointing from the phone into your eyeball.
+
+On iOS, `zIndex` may require `View`s to be siblings of each other for it to work as expected.
+
+See [MDN CSS Reference](https://developer.mozilla.org/en-US/docs/Web/CSS/z-index) for more details.
+
+| Type | Required |
+| ------ | -------- |
+| number | No |
diff --git a/cnwebsite/versioned_docs/version-0.85/layoutanimation.md b/cnwebsite/versioned_docs/version-0.85/layoutanimation.md
new file mode 100644
index 00000000000..a5449b1160e
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/layoutanimation.md
@@ -0,0 +1,358 @@
+---
+id: layoutanimation
+title: LayoutAnimation
+---
+
+在下一次布局发生时,自动为视图添加动画效果以过渡到新位置。
+
+使用此 API 的常见方式是在函数组件中更新 state hook 之前调用它,或在类组件中调用 `setState` 之前调用。
+
+请注意,要在 **Android** 上使此功能生效,你需要通过 `UIManager` 设置以下标志:
+
+```js
+if (Platform.OS === 'android') {
+ if (UIManager.setLayoutAnimationEnabledExperimental) {
+ UIManager.setLayoutAnimationEnabledExperimental(true);
+ }
+}
+```
+
+## 示例
+
+```SnackPlayer name=LayoutAnimation%20Example&supportedPlatforms=android,ios
+import React, {useState} from 'react';
+import {
+ LayoutAnimation,
+ Platform,
+ StyleSheet,
+ Text,
+ TouchableOpacity,
+ UIManager,
+ View,
+} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+if (
+ Platform.OS === 'android' &&
+ UIManager.setLayoutAnimationEnabledExperimental
+) {
+ UIManager.setLayoutAnimationEnabledExperimental(true);
+}
+const App = () => {
+ const [expanded, setExpanded] = useState(false);
+
+ return (
+
+
+ {
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
+ setExpanded(!expanded);
+ }}>
+ Press me to {expanded ? 'collapse' : 'expand'}!
+
+ {expanded && (
+
+ I disappear sometimes!
+
+ )}
+
+
+ );
+};
+
+const style = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ gap: 16,
+ },
+ tile: {
+ backgroundColor: 'lightgrey',
+ borderWidth: 0.5,
+ borderColor: '#d6d7da',
+ padding: 4,
+ },
+});
+
+export default App;
+```
+
+---
+
+# 参考文档
+
+## 方法
+
+### `configureNext()`
+
+```tsx
+static configureNext(
+ config: LayoutAnimationConfig,
+ onAnimationDidEnd?: () => void,
+ onAnimationDidFail?: () => void,
+);
+```
+
+安排在下一次布局时执行动画。
+
+#### 参数:
+
+| 名称 | 类型 | 必需 | 说明 |
+| ------------------ | -------- | ---- | -------------------- |
+| config | object | 是 | 参见下方的配置说明。 |
+| onAnimationDidEnd | function | 否 | 动画完成时调用。 |
+| onAnimationDidFail | function | 否 | 动画失败时调用。 |
+
+`config` 参数是一个包含以下键的对象。[`create`](layoutanimation.md#create) 方法会返回一个有效的 `config` 对象,[`Presets`](layoutanimation.md#presets) 中的对象也都可以作为 `config` 传入。
+
+- `duration` 持续时间(毫秒)
+- `create`,可选配置,用于为新出现的视图添加动画
+- `update`,可选配置,用于为已更新的视图添加动画
+- `delete`,可选配置,用于为被移除的视图添加动画
+
+传递给 `create`、`update` 或 `delete` 的配置包含以下键:
+
+- `type`,要使用的[动画类型](layoutanimation.md#types)
+- `property`,要进行动画的[布局属性](layoutanimation.md#properties)(可选,但建议在 `create` 和 `delete` 中使用)
+- `springDamping`(数字,可选,仅在 `type: Type.spring` 时使用)
+- `initialVelocity`(数字,可选)
+- `delay`(数字,可选)
+- `duration`(数字,可选)
+
+---
+
+### `create()`
+
+```tsx
+static create(duration, type, creationProp)
+```
+
+辅助方法,创建一个包含 `create`、`update` 和 `delete` 字段的对象,用于传递给 [`configureNext`](layoutanimation.md#configurenext)。`type` 参数是一个[动画类型](layoutanimation.md#types),`creationProp` 参数是一个[布局属性](layoutanimation.md#properties)。
+
+**示例:**
+
+```SnackPlayer name=LayoutAnimation&supportedPlatforms=android,ios
+import React, {useState} from 'react';
+import {
+ View,
+ Platform,
+ UIManager,
+ LayoutAnimation,
+ StyleSheet,
+ Button,
+} from 'react-native';
+
+if (
+ Platform.OS === 'android' &&
+ UIManager.setLayoutAnimationEnabledExperimental
+) {
+ UIManager.setLayoutAnimationEnabledExperimental(true);
+}
+
+const App = () => {
+ 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'},
+ });
+ setBoxPosition(boxPosition === 'left' ? 'right' : 'left');
+ };
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'flex-start',
+ justifyContent: 'center',
+ },
+ box: {
+ height: 100,
+ width: 100,
+ borderRadius: 5,
+ margin: 8,
+ backgroundColor: 'blue',
+ },
+ moveRight: {
+ alignSelf: 'flex-end',
+ height: 200,
+ width: 200,
+ },
+ buttonContainer: {
+ alignSelf: 'center',
+ },
+});
+
+export default App;
+```
+
+## 属性
+
+### Types
+
+用于 [`create`](layoutanimation.md#create) 方法或 [`configureNext`](layoutanimation.md#configurenext) 的 `create`/`update`/`delete` 配置中的动画类型枚举。(使用示例:`LayoutAnimation.Types.easeIn`)
+
+| Types |
+| ------------- |
+| spring |
+| linear |
+| easeInEaseOut |
+| easeIn |
+| easeOut |
+| keyboard |
+
+---
+
+### Properties
+
+用于 [`create`](layoutanimation.md#create) 方法或 [`configureNext`](layoutanimation.md#configurenext) 的 `create`/`update`/`delete` 配置中要进行动画的布局属性枚举。(使用示例:`LayoutAnimation.Properties.opacity`)
+
+| Properties |
+| ---------- |
+| opacity |
+| scaleX |
+| scaleY |
+| scaleXY |
+
+---
+
+### Presets
+
+一组预定义的动画配置,用于传递给 [`configureNext`](layoutanimation.md#configurenext)。
+
+| Presets | 值 |
+| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 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'} }` |
+
+---
+
+### `easeInEaseOut`
+
+使用 `Presets.easeInEaseOut` 调用 `configureNext()`。
+
+---
+
+### `linear`
+
+使用 `Presets.linear` 调用 `configureNext()`。
+
+---
+
+### `spring`
+
+使用 `Presets.spring` 调用 `configureNext()`。
+
+**示例:**
+
+```SnackPlayer name=LayoutAnimation&supportedPlatforms=android,ios
+import React, {useState} from 'react';
+import {
+ View,
+ Platform,
+ UIManager,
+ LayoutAnimation,
+ StyleSheet,
+ Button,
+} from 'react-native';
+
+if (
+ 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 toggleFirstBox = () => {
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.easeInEaseOut);
+ setFirstBoxPosition(firstBoxPosition === 'left' ? 'right' : 'left');
+ };
+
+ const toggleSecondBox = () => {
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.linear);
+ setSecondBoxPosition(secondBoxPosition === 'left' ? 'right' : 'left');
+ };
+
+ const toggleThirdBox = () => {
+ LayoutAnimation.configureNext(LayoutAnimation.Presets.spring);
+ setThirdBoxPosition(thirdBoxPosition === 'left' ? 'right' : 'left');
+ };
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'flex-start',
+ justifyContent: 'center',
+ },
+ box: {
+ height: 100,
+ width: 100,
+ borderRadius: 5,
+ margin: 8,
+ backgroundColor: 'blue',
+ },
+ moveRight: {
+ alignSelf: 'flex-end',
+ },
+ buttonContainer: {
+ alignSelf: 'center',
+ },
+});
+
+export default App;
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/layoutevent.md b/cnwebsite/versioned_docs/version-0.85/layoutevent.md
new file mode 100644
index 00000000000..68831e98603
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/layoutevent.md
@@ -0,0 +1,72 @@
+---
+id: layoutevent
+title: LayoutEvent 对象类型
+---
+
+`LayoutEvent` 对象作为组件布局变化的结果在回调中返回,例如 [View](view) 组件中的 `onLayout`。
+
+## 示例
+
+```js
+{
+ layout: {
+ width: 520,
+ height: 70.5,
+ x: 0,
+ y: 42.5
+ },
+ target: 1127
+}
+```
+
+## 属性与值
+
+### `height`
+
+布局变化后组件的高度。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `width`
+
+布局变化后组件的宽度。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `x`
+
+组件在父组件内的 X 坐标。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `y`
+
+组件在父组件内的 Y 坐标。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `target`
+
+接收 LayoutEvent 的元素的节点 ID。
+
+| 类型 | 可选 |
+| --------------------------- | ---- |
+| number, `null`, `undefined` | 否 |
+
+## 被下列组件引用
+
+- [`Image`](image)
+- [`Pressable`](pressable)
+- [`ScrollView`](scrollview)
+- [`Text`](text)
+- [`TextInput`](textinput)
+- [`TouchableWithoutFeedback`](touchablewithoutfeedback)
+- [`View`](view)
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/direct-manipulation.md b/cnwebsite/versioned_docs/version-0.85/legacy/direct-manipulation.md
new file mode 100644
index 00000000000..25bd9749807
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/direct-manipulation.md
@@ -0,0 +1,441 @@
+---
+id: direct-manipulation
+title: 直接操作
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+有时候我们需要直接改动组件并触发局部的刷新,但不使用 state 或是 props。譬如在浏览器中使用 React 库,有时候会需要直接修改一个 DOM 节点,而在手机 App 中操作 View 时也会碰到同样的情况。在 React Native 中,`setNativeProps`就是等价于直接操作 DOM 节点的方法。
+
+:::caution 注意
+什么时候使用 setNativeProps 呢?在(不得不)频繁刷新而又遇到了性能瓶颈的时候。
+
+直接操作组件并不是应该经常使用的工具。一般来说只是用来创建连续的动画,同时避免渲染组件结构和同步太多视图变化所带来的大量开销。`setNativeProps`是一个“简单粗暴”的方法,它直接在底层(DOM、UIView 等)而不是 React 组件中记录 state,这样会使代码逻辑难以理清。所以在使用这个方法之前,请尽量先尝试用`setState`和[shouldComponentUpdate](https://zh-hans.reactjs.org/docs/optimizing-performance.html#shouldcomponentupdate-in-action)方法来解决问题。
+:::
+
+## setNativeProps 与 TouchableOpacity
+
+[TouchableOpacity](https://github.com/facebook/react-native/blob/master/Libraries/Components/Touchable/TouchableOpacity.js)这个组件就在内部使用了`setNativeProps`方法来更新其子组件的透明度:
+
+```tsx
+const viewRef = useRef();
+const setOpacityTo = useCallback(value => {
+ // Redacted: animation related code
+ viewRef.current.setNativeProps({
+ opacity: value,
+ });
+}, []);
+```
+
+由此我们可以写出下面这样的代码:子组件可以响应点击事件,更改自己的透明度。而子组件自身并不需要处理这件事情,也不需要在实现中做任何修改。
+
+```jsx
+
+
+ Press me!
+
+
+```
+
+如果不使用`setNativeProps`来实现这一需求,那么一种可能的办法是把透明值保存到 state 中,然后在`onPress`事件触发时更新这个值:
+
+```tsx
+const [buttonOpacity, setButtonOpacity] = useState(1);
+return (
+ setButtonOpacity(0.5)}
+ onPressOut={() => setButtonOpacity(1)}>
+
+ Press me!
+
+
+);
+```
+
+比起之前的例子,这一做法会消耗大量的计算 —— 每一次透明值变更的时候 React 都要重新渲染组件结构,即便视图的其他属性和子组件并没有变化。一般来说这一开销也不足为虑,但当执行连续的动画以及响应用户手势的时候,只有正确地优化组件才能提高动画的流畅度。
+
+如果你看过[NativeMethodsMixin](https://github.com/facebook/react-native/blob/master/Libraries/Renderer/oss/ReactNativeRenderer-prod.js)中的`setNativeProps`方法的实现,你就会发现它实际是对`RCTUIManager.updateView`的封装 —— 而这正是重渲染所触发的函数调用,具体可以参看[ReactNativeBaseComponent.js 中的 receiveComponent](https://github.com/facebook/react/blob/master/src/renderers/native/ReactNativeBaseComponent.js).
+
+## 复合组件与 setNativeProps
+
+复合组件并不是单纯的由一个原生视图构成,所以你不能对其直接使用`setNativeProps`。比如下面这个例子:
+
+
+
+
+```SnackPlayer name=setNativeProps%20with%20Composite%20Components&ext=js
+import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = props => (
+
+ {props.label}
+
+);
+
+const App = () => (
+
+
+
+);
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=setNativeProps%20with%20Composite%20Components&ext=tsx
+import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = (props: {label: string}) => (
+
+ {props.label}
+
+);
+
+const App = () => (
+
+
+
+);
+
+export default App;
+```
+
+
+
+
+跑这个例子会马上看到一行报错: `Touchable child must either be native or forward setNativeProps to a native component`。这是因为`MyButton`并非直接由原生视图构成,而我们只能给原生视图设置透明值。你可以尝试这样去理解:如果你通过`createReactClass`方法自定义了一个组件,直接给它设置样式 prop 是不会生效的,你得把样式 props 层层向下传递给子组件,直到子组件是一个能够直接定义样式的原生组件。同理,我们也需要把`setNativeProps`传递给由原生组件封装的子组件。
+
+#### 将 setNativeProps 传递给子组件
+
+由于`setNativeProps`方法存在于对`View`组件的任何 ref 上,所以只需将自定义组件上的 ref 转发到其渲染的某个` `组件即可。这意味着在自定义组件上调用`setNativeProps`与直接在被包装的`View`组件上调用`setNativeProps`具有相同的效果。
+
+
+
+
+```SnackPlayer name=Forwarding%20setNativeProps&ext=js
+import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = React.forwardRef((props, ref) => (
+
+ {props.label}
+
+));
+
+const App = () => (
+
+
+
+);
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Forwarding%20setNativeProps&ext=tsx
+import React from 'react';
+import {Text, TouchableOpacity, View} from 'react-native';
+
+const MyButton = React.forwardRef((props, ref) => (
+
+ {props.label}
+
+));
+
+const App = () => (
+
+
+
+);
+
+export default App;
+```
+
+
+
+
+现在你可以在`TouchableOpacity`中使用`MyButton`了!
+
+你可能还会注意到我们在向下传递 props 时使用了`{...props}`语法。这是因为`TouchableOpacity`本身其实也是个复合组件,它除了要求在子组件上执行`setNativeProps`以外,还要求子组件对触摸事件进行处理。因此,它会传递多个 props,其中包含了[onmoveshouldsetresponder](view.md#onmoveshouldsetresponder) 函数,这个函数需要回调给`TouchableOpacity`组件,以完成触摸事件的处理。与之相对的是`TouchableHighlight`组件,它本身是由原生视图构成,因而只需要我们实现`setNativeProps`。
+
+## 使用 setNativeProps 来直接编辑输入框的值
+
+`setNativeProps` 的另一个常见用途是编辑 TextInput 的值。TextInput 的 `controlled` prop 有时在 `bufferDelay` 较低且用户输入速度非常快时可能会丢失字符。有些开发者更喜欢完全跳过这个 prop,而是在必要时使用 `setNativeProps` 直接操作 TextInput 的值。例如,以下代码演示了在点击按钮时编辑输入框:
+
+
+
+
+```SnackPlayer name=Clear%20text&ext=js
+import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+ StyleSheet,
+ TextInput,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+
+const App = () => {
+ const inputRef = useRef(null);
+ const editText = useCallback(() => {
+ inputRef.current.setNativeProps({text: 'Edited Text'});
+ }, []);
+
+ return (
+
+
+
+ Edit text
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ input: {
+ height: 50,
+ width: 200,
+ marginHorizontal: 20,
+ borderWidth: 1,
+ borderColor: '#ccc',
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Clear%20text&ext=tsx
+import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+ StyleSheet,
+ TextInput,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+
+const App = () => {
+ const inputRef = useRef(null);
+ const editText = useCallback(() => {
+ inputRef.current?.setNativeProps({text: 'Edited Text'});
+ }, []);
+
+ return (
+
+
+
+ Edit text
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ input: {
+ height: 50,
+ width: 200,
+ marginHorizontal: 20,
+ borderWidth: 1,
+ borderColor: '#ccc',
+ },
+});
+
+export default App;
+```
+
+
+
+
+你可以使用 [`clear`](../textinput#clear) 方法来清除 `TextInput`,它使用相同的方法清除当前输入文本。
+
+## 避免和 render 方法的冲突
+
+如果要更新一个由 render 方法来维护的属性,则可能会碰到一些出人意料的 bug。因为每一次组件重新渲染都可能引起属性变化,这样一来,之前通过`setNativeProps`所设定的值就被完全忽略和覆盖掉了。
+
+## setNativeProps 与 shouldComponentUpdate
+
+通过[巧妙运用`shouldComponentUpdate`方法](https://facebook.github.io/react/docs/advanced-performance.html#avoiding-reconciling-the-dom),可以避免重新渲染那些实际没有变化的子组件所带来的额外开销,此时使用`setState`的性能已经可以与`setNativeProps`相媲美了。
+
+## 其他原生方法
+
+此处描述的方法大多数 React Native 已经提供。但是这些在组合组件是不支持的,因为原生的视图不提供支持,包含你自己的应用中你自定的绝大多数组件
+
+### measure(callback)
+
+测量视图在屏幕上的坐标、宽度、高度,异步回调这些参数。如果测量成功则回调如下参数:
+
+- x
+- y
+- width
+- height
+- pageX
+- pageY
+
+注意,这些参数必须在组件原生端渲染完成后才能返回视图测量值。若你想尽快的获取视图组件的测量值(且不需要`pageX`和`pageY`),可考虑使用[`onLayout` prop](view.md#onlayout) 来实现。
+
+Also the width and height returned by `measure()` are the width and height of the component in the viewport. If you need the actual size of the component, consider using the [`onLayout`](view.md#onlayout) property instead.
+
+### measureInWindow(callback)
+
+获取指定视图在窗口上的位置,异步返回量测值。如果根视图在另一个视图上,将返回绝对的位置。获取成功返回如下参数:
+
+- x
+- y
+- width
+- height
+
+### measureLayout(relativeToNativeComponentRef, onSuccess, onFail)
+
+类似`measure()`方法,测量相对于祖视图(通过`relativeToNativeComponentRef`来指定)的位置关系。返回的是相对于祖视图原点的`x`、`y`。
+
+:::note
+此方法也可以使用 `relativeToNativeNode` 处理器(而不是引用)来调用,但这种变体在新架构中已被废弃。
+:::
+
+
+
+
+```SnackPlayer name=measureLayout%20example&supportedPlatforms=android,ios&ext=js
+import React, {useEffect, useRef, useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+
+const App = () => {
+ const textContainerRef = useRef(null);
+ const textRef = useRef(null);
+ const [measure, setMeasure] = useState(null);
+
+ useEffect(() => {
+ if (textRef.current && textContainerRef.current) {
+ textRef.current.measureLayout(
+ textContainerRef.current,
+ (left, top, width, height) => {
+ setMeasure({left, top, width, height});
+ },
+ );
+ }
+ }, [measure]);
+
+ return (
+
+
+ Where am I? (relative to the text container)
+
+ {JSON.stringify(measure)}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ },
+ textContainer: {
+ backgroundColor: '#61dafb',
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: 12,
+ },
+ measure: {
+ textAlign: 'center',
+ padding: 12,
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=measureLayout%20example&ext=tsx
+import React, {useEffect, useRef, useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+
+type Measurements = {
+ left: number;
+ top: number;
+ width: number;
+ height: number;
+};
+
+const App = () => {
+ const textContainerRef = useRef(null);
+ const textRef = useRef(null);
+ const [measure, setMeasure] = useState(null);
+
+ useEffect(() => {
+ if (textRef.current && textContainerRef.current) {
+ textRef.current?.measureLayout(
+ textContainerRef.current,
+ (left, top, width, height) => {
+ setMeasure({left, top, width, height});
+ },
+ () => {
+ console.error('measurement failed');
+ },
+ );
+ }
+ }, [measure]);
+
+ return (
+
+
+ Where am I? (relative to the text container)
+
+ {JSON.stringify(measure)}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ },
+ textContainer: {
+ backgroundColor: '#61dafb',
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: 12,
+ },
+ measure: {
+ textAlign: 'center',
+ padding: 12,
+ },
+});
+
+export default App;
+```
+
+
+
+
+### focus()
+
+获取给定输入框或者视图的焦点。更进一步的变换操作依赖与不同的平台和不同的视图。
+
+### blur()
+
+与 `focus()` 方法相反,该方法用来移除给定视图或者输入框的焦点。
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/local-library-setup.md b/cnwebsite/versioned_docs/version-0.85/legacy/local-library-setup.md
new file mode 100644
index 00000000000..fff5daefaed
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/local-library-setup.md
@@ -0,0 +1,94 @@
+---
+id: local-library-setup
+title: Local libraries setup
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+A local library is a library containing views or modules that's local to your app and not published to a registry. This is different from the traditional setup for view and modules in the sense that a local library is decoupled from your app's native code.
+
+The local library is created outside of the `android/` and `ios/` folders and makes use of autolinking to integrate with your app. The structure with a local library may look like this:
+
+```plaintext
+MyApp
+├── node_modules
+├── modules <-- folder for your local libraries
+│ └── awesome-module <-- your local library
+├── android
+├── ios
+├── src
+├── index.js
+└── package.json
+```
+
+Since a local library's code exists outside of `android/` and `ios/` folders, it makes it easier to upgrade React Native versions in the future, copy to other projects etc.
+
+To create local library we will use [create-react-native-library](https://callstack.github.io/react-native-builder-bob/create). This tool contains all the necessary templates.
+
+### Getting Started
+
+Inside your React Native application's root folder, run the following command:
+
+```shell
+npx create-react-native-library@latest awesome-module
+```
+
+Where `awesome-module` is the name you would like for the new module. After going through the prompts, you will have a new folder called `modules` in your project's root directory which contains the new module.
+
+### Linking
+
+By default, the generated library is automatically linked to the project using `link:` protocol when using Yarn and `file:` when using npm:
+
+
+
+
+
+```json
+"dependencies": {
+ "awesome-module": "file:./modules/awesome-module"
+}
+```
+
+
+
+
+```json
+"dependencies": {
+ "awesome-module": "link:./modules/awesome-module"
+}
+```
+
+
+
+
+This creates a symlink to the library under `node_modules` which makes autolinking work.
+
+### Installing dependencies
+
+To link the module you need to install dependencies:
+
+
+
+
+
+```shell
+npm install
+```
+
+
+
+
+```shell
+yarn install
+```
+
+
+
+
+### Using module inside your app
+
+To use the module inside your app, you can import it by its name:
+
+```js
+import {multiply} from 'awesome-module';
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/native-components-android.md b/cnwebsite/versioned_docs/version-0.85/legacy/native-components-android.md
new file mode 100644
index 00000000000..078b3d5d0ef
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/native-components-android.md
@@ -0,0 +1,865 @@
+---
+id: native-components-android
+title: Android 原生UI组件
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecation.mdx'
+
+
+
+在如今的 App 中,已经有成千上万的原生 UI 部件了——其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多。React Native 已经封装了大部分最常见的组件,譬如`ScrollView`和`TextInput`,但不可能封装全部组件。而且,说不定你曾经为自己以前的 App 还封装过一些组件,React Native 肯定没法包含它们。幸运的是,在 React Naitve 应用程序中封装和植入已有的组件非常简单。
+
+和原生模块向导一样,本向导也是一个相对高级的向导,我们假设你已经对 Android 编程颇有经验。本向导会引导你如何构建一个原生 UI 组件,带领你了解 React Native 核心库中`ImageView`组件的具体实现。
+
+:::info
+您还可以通过一个命令来配置生成包含原生组件的本地库模板。阅读[本地库设置](local-library-setup)指南以获取更多详细信息。
+:::
+
+## ImageView 示例
+
+在这个例子里,我们来看看为了让 JavaScript 中可以使用 ImageView,需要做哪些准备工作。
+
+原生视图需要被一个`ViewManager`的派生类(或者更常见的,`SimpleViewManager`的派生类)创建和管理。一个`SimpleViewManager`可以用于这个场景,是因为它能够包含更多公共的属性,譬如背景颜色、透明度、Flexbox 布局等等。
+
+这些子类本质上都是单例——React Native 只会为每个管理器创建一个实例。它们创建原生的视图并提供给`NativeViewHierarchyManager`,NativeViewHierarchyManager 则会反过来委托它们在需要的时候去设置和更新视图的属性。`ViewManager`还会代理视图的所有委托,并给 JavaScript 发回对应的事件。
+
+提供原生视图很简单:
+
+1. 创建一个 ViewManager 的子类。
+2. 实现`createViewInstance`方法。
+3. 导出视图的属性设置器:使用`@ReactProp`(或`@ReactPropGroup`)注解。
+4. 把这个视图管理类注册到应用程序包的`createViewManagers`里。
+5. 实现 JavaScript 模块。
+
+## 1. 创建`ViewManager`的子类
+
+在这个例子里我们创建一个视图管理类`ReactImageManager`,它继承自`SimpleViewManager`。`ReactImageView`是这个视图管理类所管理的对象类型,也就是我们自定义的原生视图。`getName`方法返回的名字会用于在 JavaScript 端引用。
+
+
+
+
+```kotlin
+class ReactImageManager(
+ private val callerContext: ReactApplicationContext
+) : SimpleViewManager() {
+
+ override fun getName() = REACT_CLASS
+
+ companion object {
+ const val REACT_CLASS = "RCTImageView"
+ }
+}
+```
+
+
+
+
+```java
+public class ReactImageManager extends SimpleViewManager {
+
+ public static final String REACT_CLASS = "RCTImageView";
+ ReactApplicationContext mCallerContext;
+
+ public ReactImageManager(ReactApplicationContext reactContext) {
+ mCallerContext = reactContext;
+ }
+
+ @Override
+ public String getName() {
+ return REACT_CLASS;
+ }
+}
+```
+
+
+
+
+## 2. 实现方法`createViewInstance`
+
+视图在`createViewInstance`中创建,且应当把自己初始化为默认的状态。所有属性的设置都通过后续的`updateView`来进行。
+
+
+
+
+```kotlin
+ override fun createViewInstance(context: ThemedReactContext) =
+ ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, callerContext)
+```
+
+
+
+
+```java
+ @Override
+ public ReactImageView createViewInstance(ThemedReactContext context) {
+ return new ReactImageView(context, Fresco.newDraweeControllerBuilder(), null, mCallerContext);
+ }
+```
+
+
+
+
+## 3. 通过`@ReactProp`(或`@ReactPropGroup`)注解来导出属性的设置方法。
+
+要导出给 JavaScript 使用的属性,需要申明带有`@ReactProp`(或`@ReactPropGroup`)注解的设置方法。方法的第一个参数是要修改属性的视图实例,第二个参数是要设置的属性值。方法的返回值类型必须为`void`,在 Kotlin 中是 `Unit`,而且访问控制必须被声明为`public`。JavaScript 所得知的属性类型会由该方法第二个参数的类型来自动决定。支持的类型有:`boolean`, `int`, `float`, `double`, `String`, `Boolean`, `Integer`, `ReadableArray`, `ReadableMap`。Kotlin 中对应的则是 `Boolean`, `Int`, `Float`, `Double`, `String`, `ReadableArray`, `ReadableMap`.
+
+`@ReactProp`注解必须包含一个字符串类型的参数`name`。这个参数指定了对应属性在 JavaScript 端的名字。
+
+除了`name`,`@ReactProp`注解还接受这些可选的参数:`defaultBoolean`, `defaultInt`, `defaultFloat`。这些参数必须是对应的基础类型的值(也就是对应 Java 中的 `boolean`, `int`, `float`, 或是 Kotlin 中的 `Boolean`, `Int`, `Float`),这些值会被传递给 setter 方法,以免 JavaScript 端某些情况下在组件中移除了对应的属性。注意这个"默认"值只对基本类型生效,对于其他的类型而言,当对应的属性删除时,`null`会作为默认值提供给方法。
+
+使用`@ReactPropGroup`来注解的设置方法和`@ReactProp`不同。请参见`@ReactPropGroup`注解类源代码中的文档来获取更多详情。
+
+**重要!** 在 ReactJS 里,修改一个属性会引发一次对设置方法的调用。有一种修改情况是,移除掉之前设置的属性。在这种情况下设置方法也一样会被调用,并且“默认”值会被作为参数提供(对于基础类型来说可以通过`defaultBoolean`、`defaultFloat`等`@ReactProp`的属性提供,而对于复杂类型来说参数则会设置为`null`)
+
+
+
+
+```kotlin
+ @ReactProp(name = "src")
+ fun setSrc(view: ReactImageView, sources: ReadableArray?) {
+ view.setSource(sources)
+ }
+
+ @ReactProp(name = "borderRadius", defaultFloat = 0f)
+ override fun setBorderRadius(view: ReactImageView, borderRadius: Float) {
+ view.setBorderRadius(borderRadius)
+ }
+
+ @ReactProp(name = ViewProps.RESIZE_MODE)
+ fun setResizeMode(view: ReactImageView, resizeMode: String?) {
+ view.setScaleType(ImageResizeMode.toScaleType(resizeMode))
+ }
+```
+
+
+
+
+```java
+ @ReactProp(name = "src")
+ public void setSrc(ReactImageView view, @Nullable ReadableArray sources) {
+ view.setSource(sources);
+ }
+
+ @ReactProp(name = "borderRadius", defaultFloat = 0f)
+ public void setBorderRadius(ReactImageView view, float borderRadius) {
+ view.setBorderRadius(borderRadius);
+ }
+
+ @ReactProp(name = ViewProps.RESIZE_MODE)
+ public void setResizeMode(ReactImageView view, @Nullable String resizeMode) {
+ view.setScaleType(ImageResizeMode.toScaleType(resizeMode));
+ }
+```
+
+
+
+
+## 4. 注册`ViewManager`
+
+最后一步就是把视图控制器注册到应用中。这和[原生模块](native-modules-android.md)的注册方法类似,唯一的区别是我们把它放到`createViewManagers`方法的返回值里。
+
+
+
+
+```kotlin
+ override fun createViewManagers(
+ reactContext: ReactApplicationContext
+ ) = listOf(ReactImageManager(reactContext))
+```
+
+
+
+
+```java
+ @Override
+ public List createViewManagers(
+ ReactApplicationContext reactContext) {
+ return Arrays.asList(
+ new ReactImageManager(reactContext)
+ );
+ }
+```
+
+
+
+
+完成上面这些代码后,请一定记得要重新编译!(运行`yarn android`命令)
+
+## 5. 实现对应的 JavaScript 模块
+
+整个过程的最后一步就是创建 JavaScript 模块并且定义 Java 和 JavaScript 之间的接口层。我们建议你使用 TypeScript 来规范定义接口的具体结构,或者至少用注释说明清楚(老版本的 RN 使用`propTypes`来规范接口定义,这一做法已不再支持)。
+
+```tsx title="ImageView.tsx"
+import {requireNativeComponent} from 'react-native';
+
+/**
+ * Composes `View`.
+ *
+ * - src: Array<{url: string}>
+ * - borderRadius: number
+ * - resizeMode: 'cover' | 'contain' | 'stretch'
+ */
+export default requireNativeComponent('RCTImageView');
+```
+
+`requireNativeComponent`目前只接受一个参数,即原生视图的名字。如果你还需要做一些复杂的逻辑譬如事件处理,那么可以把原生组件用一个普通 React 组件封装。后文的`MyCustomView`例子里演示了这种用法。
+
+# 事件
+
+现在我们已经知道了怎么导出一个原生视图组件,并且我们可以在 JS 里很方便的控制它了。不过我们怎么才能处理来自用户的事件,譬如缩放操作或者拖动?当一个原生事件发生的时候,它应该也能触发 JavaScript 端视图上的事件,这两个视图会依据`getId()`而关联在一起。
+
+
+
+
+```kotlin
+class MyCustomView(context: Context) : View(context) {
+ ...
+ fun onReceiveNativeEvent() {
+ val event = Arguments.createMap().apply {
+ putString("message", "MyMessage")
+ }
+ val reactContext = context as ReactContext
+ reactContext
+ .getJSModule(RCTEventEmitter::class.java)
+ .receiveEvent(id, "topChange", event)
+ }
+}
+```
+
+
+
+
+```java
+class MyCustomView extends View {
+ ...
+ public void onReceiveNativeEvent() {
+ WritableMap event = Arguments.createMap();
+ event.putString("message", "MyMessage");
+ ReactContext reactContext = (ReactContext)getContext();
+ reactContext
+ .getJSModule(RCTEventEmitter.class)
+ .receiveEvent(getId(), "topChange", event);
+ }
+}
+```
+
+
+
+
+要把事件名`topChange`映射到 JavaScript 端的`onChange`回调属性上,需要在你的`ViewManager`中覆盖`getExportedCustomBubblingEventTypeConstants`方法,并在其中进行注册:
+
+
+
+
+```kotlin
+class ReactImageManager : SimpleViewManager() {
+ ...
+ override fun getExportedCustomBubblingEventTypeConstants(): Map {
+ return mapOf(
+ "topChange" to mapOf(
+ "phasedRegistrationNames" to mapOf(
+ "bubbled" to "onChange"
+ )
+ )
+ )
+ }
+}
+```
+
+
+
+
+```java
+public class ReactImageManager extends SimpleViewManager {
+ ...
+ public Map getExportedCustomBubblingEventTypeConstants() {
+ return MapBuilder.builder().put(
+ "topChange",
+ MapBuilder.of(
+ "phasedRegistrationNames",
+ MapBuilder.of("bubbled", "onChange")
+ )
+ ).build();
+ }
+}
+```
+
+
+
+
+这个回调会传递一个原生事件对象,一般来说我们会在封装组件里进行处理以便外部使用:
+
+```tsx title="MyCustomView.tsx"
+import React, {useCallback} from 'react';
+
+const MyCustomView = ({onChangeMessage, ...props}) => {
+ const onChange = useCallback(
+ event => {
+ if (!onChangeMessage) {
+ return;
+ }
+ onChangeMessage(event.nativeEvent.message);
+ },
+ [onChangeMessage],
+ );
+
+ return ;
+};
+
+const RCTMyCustomView = requireNativeComponent(`RCTMyCustomView`);
+```
+
+# 与 Android Fragment 的整合实例
+
+为了将现有的原生 UI 元素整合到 React Native 应用中,你可能需要使用 Android Fragments 来对本地组件进行更精细的控制,而不是从 `ViewManager` 返回一个 `View`。如果你想在[生命周期方法](https://developer.android.com/guide/fragments/lifecycle)的帮助下添加与视图绑定的自定义逻辑,如`onViewCreated`、`onPause`、`onResume`,你会用得到它。下面的步骤将告诉你如何做到这一点:
+
+### 1. 创建一个自定义视图
+
+首先,我们创建一个继承自`FrameLayout`的`CustomView`类(这个视图的内容可以是您想要渲染的任何视图)
+
+
+
+
+```kotlin title="CustomView.kt"
+// replace with your package
+package com.mypackage
+
+import android.content.Context
+import android.graphics.Color
+import android.widget.FrameLayout
+import android.widget.TextView
+
+class CustomView(context: Context) : FrameLayout(context) {
+ init {
+ // set padding and background color
+ setPadding(16,16,16,16)
+ setBackgroundColor(Color.parseColor("#5FD3F3"))
+
+ // add default text view
+ addView(TextView(context).apply {
+ text = "Welcome to Android Fragments with React Native."
+ })
+ }
+}
+```
+
+
+
+
+```java title="CustomView.java"
+// replace with your package
+package com.mypackage;
+
+import android.content.Context;
+import android.graphics.Color;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+
+public class CustomView extends FrameLayout {
+ public CustomView(@NonNull Context context) {
+ super(context);
+ // set padding and background color
+ this.setPadding(16,16,16,16);
+ this.setBackgroundColor(Color.parseColor("#5FD3F3"));
+
+ // add default text view
+ TextView text = new TextView(context);
+ text.setText("Welcome to Android Fragments with React Native.");
+ this.addView(text);
+ }
+}
+```
+
+
+
+
+### 2. 创建一个 `Fragment`
+
+
+
+
+```kotlin title="MyFragment.kt"
+// replace with your package
+package com.mypackage
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.fragment.app.Fragment
+
+// replace with your view's import
+import com.mypackage.CustomView
+
+class MyFragment : Fragment() {
+ private lateinit var customView: CustomView
+
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ super.onCreateView(inflater, container, savedInstanceState)
+ customView = CustomView(requireNotNull(context))
+ return customView // this CustomView could be any view that you want to render
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+ // do any logic that should happen in an `onCreate` method, e.g:
+ // customView.onCreate(savedInstanceState);
+ }
+
+ override fun onPause() {
+ super.onPause()
+ // do any logic that should happen in an `onPause` method
+ // e.g.: customView.onPause();
+ }
+
+ override fun onResume() {
+ super.onResume()
+ // do any logic that should happen in an `onResume` method
+ // e.g.: customView.onResume();
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ // do any logic that should happen in an `onDestroy` method
+ // e.g.: customView.onDestroy();
+ }
+}
+```
+
+
+
+
+```java title="MyFragment.java"
+// replace with your package
+package com.mypackage;
+
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import androidx.fragment.app.Fragment;
+
+// replace with your view's import
+import com.mypackage.CustomView;
+
+public class MyFragment extends Fragment {
+ CustomView customView;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+ super.onCreateView(inflater, parent, savedInstanceState);
+ customView = new CustomView(this.getContext());
+ return customView; // this CustomView could be any view that you want to render
+ }
+
+ @Override
+ public void onViewCreated(View view, Bundle savedInstanceState) {
+ super.onViewCreated(view, savedInstanceState);
+ // do any logic that should happen in an `onCreate` method, e.g:
+ // customView.onCreate(savedInstanceState);
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ // do any logic that should happen in an `onPause` method
+ // e.g.: customView.onPause();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ // do any logic that should happen in an `onResume` method
+ // e.g.: customView.onResume();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ // do any logic that should happen in an `onDestroy` method
+ // e.g.: customView.onDestroy();
+ }
+}
+```
+
+
+
+
+### 3. 创建 `ViewManager` 子类
+
+
+
+
+```kotlin title="MyViewManager.kt"
+// replace with your package
+package com.mypackage
+
+import android.view.Choreographer
+import android.view.View
+import android.view.ViewGroup
+import android.widget.FrameLayout
+import androidx.fragment.app.FragmentActivity
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.bridge.ReadableArray
+import com.facebook.react.uimanager.ThemedReactContext
+import com.facebook.react.uimanager.ViewGroupManager
+import com.facebook.react.uimanager.annotations.ReactPropGroup
+
+class MyViewManager(
+ private val reactContext: ReactApplicationContext
+) : ViewGroupManager() {
+ private var propWidth: Int? = null
+ private var propHeight: Int? = null
+
+ override fun getName() = REACT_CLASS
+
+ /**
+ * Return a FrameLayout which will later hold the Fragment
+ */
+ override fun createViewInstance(reactContext: ThemedReactContext) =
+ FrameLayout(reactContext)
+
+ /**
+ * Map the "create" command to an integer
+ */
+ override fun getCommandsMap() = mapOf("create" to COMMAND_CREATE)
+
+ /**
+ * Handle "create" command (called from JS) and call createFragment method
+ */
+ override fun receiveCommand(
+ root: FrameLayout,
+ commandId: String,
+ args: ReadableArray?
+ ) {
+ super.receiveCommand(root, commandId, args)
+ val reactNativeViewId = requireNotNull(args).getInt(0)
+
+ when (commandId.toInt()) {
+ COMMAND_CREATE -> createFragment(root, reactNativeViewId)
+ }
+ }
+
+ @ReactPropGroup(names = ["width", "height"], customType = "Style")
+ fun setStyle(view: FrameLayout, index: Int, value: Int) {
+ if (index == 0) propWidth = value
+ if (index == 1) propHeight = value
+ }
+
+ /**
+ * Replace your React Native view with a custom fragment
+ */
+ fun createFragment(root: FrameLayout, reactNativeViewId: Int) {
+ val parentView = root.findViewById(reactNativeViewId)
+ setupLayout(parentView)
+
+ val myFragment = MyFragment()
+ val activity = reactContext.currentActivity as FragmentActivity
+ activity.supportFragmentManager
+ .beginTransaction()
+ .replace(reactNativeViewId, myFragment, reactNativeViewId.toString())
+ .commit()
+ }
+
+ fun setupLayout(view: View) {
+ Choreographer.getInstance().postFrameCallback(object: Choreographer.FrameCallback {
+ override fun doFrame(frameTimeNanos: Long) {
+ manuallyLayoutChildren(view)
+ view.viewTreeObserver.dispatchOnGlobalLayout()
+ Choreographer.getInstance().postFrameCallback(this)
+ }
+ })
+ }
+
+ /**
+ * Layout all children properly
+ */
+ private fun manuallyLayoutChildren(view: View) {
+ // propWidth and propHeight coming from react-native props
+ val width = requireNotNull(propWidth)
+ val height = requireNotNull(propHeight)
+
+ view.measure(
+ View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY))
+
+ view.layout(0, 0, width, height)
+ }
+
+ companion object {
+ private const val REACT_CLASS = "MyViewManager"
+ private const val COMMAND_CREATE = 1
+ }
+}
+```
+
+
+
+
+```java title="MyViewManager.java"
+// replace with your package
+package com.mypackage;
+
+import android.view.Choreographer;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import androidx.fragment.app.FragmentActivity;
+
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReadableArray;
+import com.facebook.react.common.MapBuilder;
+import com.facebook.react.uimanager.annotations.ReactProp;
+import com.facebook.react.uimanager.annotations.ReactPropGroup;
+import com.facebook.react.uimanager.ViewGroupManager;
+import com.facebook.react.uimanager.ThemedReactContext;
+
+import java.util.Map;
+
+public class MyViewManager extends ViewGroupManager {
+
+ public static final String REACT_CLASS = "MyViewManager";
+ public final int COMMAND_CREATE = 1;
+ private int propWidth;
+ private int propHeight;
+
+ ReactApplicationContext reactContext;
+
+ public MyViewManager(ReactApplicationContext reactContext) {
+ this.reactContext = reactContext;
+ }
+
+ @Override
+ public String getName() {
+ return REACT_CLASS;
+ }
+
+ /**
+ * Return a FrameLayout which will later hold the Fragment
+ */
+ @Override
+ public FrameLayout createViewInstance(ThemedReactContext reactContext) {
+ return new FrameLayout(reactContext);
+ }
+
+ /**
+ * Map the "create" command to an integer
+ */
+ @Nullable
+ @Override
+ public Map getCommandsMap() {
+ return MapBuilder.of("create", COMMAND_CREATE);
+ }
+
+ /**
+ * Handle "create" command (called from JS) and call createFragment method
+ */
+ @Override
+ public void receiveCommand(
+ @NonNull FrameLayout root,
+ String commandId,
+ @Nullable ReadableArray args
+ ) {
+ super.receiveCommand(root, commandId, args);
+ int reactNativeViewId = args.getInt(0);
+ int commandIdInt = Integer.parseInt(commandId);
+
+ switch (commandIdInt) {
+ case COMMAND_CREATE:
+ createFragment(root, reactNativeViewId);
+ break;
+ default: {}
+ }
+ }
+
+ @ReactPropGroup(names = {"width", "height"}, customType = "Style")
+ public void setStyle(FrameLayout view, int index, Integer value) {
+ if (index == 0) {
+ propWidth = value;
+ }
+
+ if (index == 1) {
+ propHeight = value;
+ }
+ }
+
+ /**
+ * Replace your React Native view with a custom fragment
+ */
+ public void createFragment(FrameLayout root, int reactNativeViewId) {
+ ViewGroup parentView = (ViewGroup) root.findViewById(reactNativeViewId);
+ setupLayout(parentView);
+
+ final MyFragment myFragment = new MyFragment();
+ FragmentActivity activity = (FragmentActivity) reactContext.getCurrentActivity();
+ activity.getSupportFragmentManager()
+ .beginTransaction()
+ .replace(reactNativeViewId, myFragment, String.valueOf(reactNativeViewId))
+ .commit();
+ }
+
+ public void setupLayout(View view) {
+ Choreographer.getInstance().postFrameCallback(new Choreographer.FrameCallback() {
+ @Override
+ public void doFrame(long frameTimeNanos) {
+ manuallyLayoutChildren(view);
+ view.getViewTreeObserver().dispatchOnGlobalLayout();
+ Choreographer.getInstance().postFrameCallback(this);
+ }
+ });
+ }
+
+ /**
+ * Layout all children properly
+ */
+ public void manuallyLayoutChildren(View view) {
+ // propWidth and propHeight coming from react-native props
+ int width = propWidth;
+ int height = propHeight;
+
+ view.measure(
+ View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.EXACTLY),
+ View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.EXACTLY));
+
+ view.layout(0, 0, width, height);
+ }
+}
+```
+
+
+
+
+### 4. 注册 `ViewManager`
+
+
+
+
+```kotlin title="MyPackage.kt"
+// replace with your package
+package com.mypackage
+
+import com.facebook.react.ReactPackage
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.uimanager.ViewManager
+
+class MyPackage : ReactPackage {
+ ...
+ override fun createViewManagers(
+ reactContext: ReactApplicationContext
+ ) = listOf(MyViewManager(reactContext))
+}
+```
+
+
+
+
+```java title="MyPackage.java"
+// replace with your package
+package com.mypackage;
+
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.Arrays;
+import java.util.List;
+
+public class MyPackage implements ReactPackage {
+
+ @Override
+ public List createViewManagers(ReactApplicationContext reactContext) {
+ return Arrays.asList(
+ new MyViewManager(reactContext)
+ );
+ }
+
+}
+```
+
+
+
+
+### 5. 注册 `Package`
+
+
+
+
+```kotlin title="MainApplication.kt"
+override fun getPackages(): List =
+ PackageList(this).packages.apply {
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // add(MyReactNativePackage())
+ add(MyAppPackage())
+ }
+```
+
+
+
+
+```java title="MainApplication.java"
+@Override
+protected List getPackages() {
+ List packages = new PackageList(this).getPackages();
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // packages.add(new MyReactNativePackage());
+ packages.add(new MyAppPackage());
+ return packages;
+}
+```
+
+
+
+
+### 6. 执行 JavaScript 模块
+
+I. `MyViewManager.tsx`
+
+```tsx title="MyViewManager.tsx"
+import {requireNativeComponent} from 'react-native';
+export const MyViewManager =
+ requireNativeComponent('MyViewManager');
+```
+
+II. `MyView.tsx` 调用 `create` 方法
+
+```tsx title="MyView.tsx"
+import React, { useEffect, useRef } from 'react';
+import { UIManager, findNodeHandle } from 'react-native';
+import { MyViewManager } from './my-view-manager';
+const createFragment = viewId =>
+ UIManager.dispatchViewManagerCommand(
+ viewId,
+ // we are calling the 'create' command
+ UIManager.MyViewManager.Commands.create.toString(),
+ [viewId],
+ );
+
+export const MyView = ({ style }) => {
+ const ref = useRef(null);
+
+ useEffect(() => {
+ const viewId = findNodeHandle(ref.current);
+ createFragment(viewId!);
+ }, []);
+
+ return (
+
+ );
+};
+```
+
+如果您想使用公开属性设置器 `@ReactProp` (or `@ReactPropGroup`) 详见上面的 [ImageView 示例](#imageview-example)。
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/native-components-ios.md b/cnwebsite/versioned_docs/version-0.85/legacy/native-components-ios.md
new file mode 100644
index 00000000000..2781ba29bfe
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/native-components-ios.md
@@ -0,0 +1,514 @@
+---
+id: native-components-ios
+title: iOS 原生UI组件
+---
+
+import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecation.mdx'
+
+
+
+在如今的 App 中,已经有成千上万的原生 UI 部件了——其中的一些是平台的一部分,另一些可能来自于一些第三方库,而且可能你自己还收藏了很多。React Native 已经封装了大部分最常见的组件,譬如`ScrollView`和`TextInput`,但不可能封装全部组件。而且,说不定你曾经为自己以前的 App 还封装过一些组件,React Native 肯定没法包含它们。幸运的是,在 React Naitve 应用程序中封装和植入已有的组件非常简单。
+
+和原生模块向导一样,本向导也是一个相对高级的向导,我们假设你已经对 iOS 编程颇有经验。本向导会引导你如何构建一个原生 UI 组件,带领你了解 React Native 核心库中`MapView`组件的具体实现。
+
+## iOS MapView 示例
+
+假设我们要把地图组件植入到我们的 App 中——我们用到的是[`MKMapView`](https://developer.apple.com/library/prerelease/mac/documentation/MapKit/Reference/MKMapView_Class/index.html),而现在只需要让它可以在 Javascript 端使用。
+
+原生视图都需要被一个`RCTViewManager`的子类来创建和管理。这些管理器在功能上有些类似“视图控制器”,但它们实际都是单例 - React Native 只会为每个管理器创建一个实例。它们创建原生的视图并提供给`RCTUIManager`,`RCTUIManager`则会反过来委托它们在需要的时候去设置和更新视图的属性。`RCTViewManager`还会代理视图的所有委托,并给 JavaScript 发回对应的事件。
+
+提供原生视图很简单:
+
+- 首先创建一个`RCTViewManager`的子类。
+- 添加`RCT_EXPORT_MODULE()`宏标记。
+- 实现`-(UIView *)view`方法。
+
+```objectivec
+// RNTMapManager.m
+#import
+
+#import
+
+@interface RNTMapManager : RCTViewManager
+@end
+
+@implementation RNTMapManager
+
+RCT_EXPORT_MODULE(RNTMap)
+
+- (UIView *)view
+{
+ return [[MKMapView alloc] init];
+}
+
+@end
+```
+
+**注意:** 请不要在`-view`中给`UIView`实例设置`frame`或是`backgroundColor`属性。为了和 JavaScript 端的布局属性一致,React Native 会覆盖你所设置的值。 如果您需要这种粒度的操作的话,比较好的方法是用另一个`UIView`来封装你想操作的`UIView`实例,并返回外层的`UIView`。请参阅[Issue 2948](https://github.com/facebook/react-native/issues/2948)获取更多信息。
+
+> 在上例中,我们的类名使用了`RNT`前缀以避免与其它框架产生命名冲突。苹果自有框架使用了两个字符的前缀,而 React Native 则使用`RCT`作为前缀。为避免命名冲突,我们建议您在自己的类中使用`RNT`以外的其它三字符前缀。
+
+完成上面这些代码后,请一定记得要重新编译!(运行`yarn ios`命令)
+
+接下来你需要一些 Javascript 代码来让这个视图变成一个可用的 React 组件:
+
+```jsx
+// MapView.js
+
+import { requireNativeComponent } from 'react-native';
+
+// requireNativeComponent 自动把'RNTMap'解析为'RNTMapManager'
+export default requireNativeComponent('RNTMap');
+
+// MyApp.js
+
+import MapView from './MapView.js';
+
+...
+
+render() {
+ return ;
+}
+```
+
+请确认此处使用了 `RNTMap` 。我们在此对 manager 使用了 require 操作,以暴露 manager 的视图,并于 Javascript 中使用。
+
+**注意:** 在渲染时,不要忘记布局视图,否则您只能面对一个空荡荡的屏幕。
+
+```jsx
+ render() {
+ return ;
+ }
+```
+
+现在我们就已经实现了一个完整功能的地图组件了,诸如捏放和其它的手势都已经完整支持。但是现在我们还不能真正的从 Javascript 端控制它。(╯﹏╰)
+
+## 属性
+
+我们能让这个组件变得更强大的第一件事情就是要能够封装一些原生属性供 Javascript 使用。举例来说,我们希望能够禁用手指捏放操作,然后指定一个初始的地图可见区域。禁用捏放操作只需要一个布尔值类型的属性就行了,所以我们添加这么一行:
+
+```objectivec
+// RNTMapManager.m
+RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)
+```
+
+注意我们现在把类型声明为`BOOL`类型——React Native 用`RCTConvert`来在 JavaScript 和原生代码之间完成类型转换。如果转换无法完成,会产生一个“红屏”的报错提示,这样你就能立即知道代码中出现了问题。如果一切进展顺利,上面这个宏就已经包含了导出属性的全部实现。
+
+现在要想禁用捏放操作,我们只需要在 JS 里设置对应的属性:
+
+```jsx
+// MyApp.js
+
+```
+
+但这样并不能很好的说明这个组件的用法——用户要想知道我们的组件有哪些属性可以用,以及可以取什么样的值,他不得不一路翻到 Objective-C 的代码。要解决这个问题,我们可以创建一个封装组件,并且通过`PropTypes`来说明这个组件的接口。
+
+```jsx
+// MapView.js
+import PropTypes from 'prop-types';
+import React from 'react';
+import {requireNativeComponent} from 'react-native';
+
+class MapView extends React.Component {
+ render() {
+ return ;
+ }
+}
+
+MapView.propTypes = {
+ /**
+ * A Boolean value that determines whether the user may use pinch
+ * gestures to zoom in and out of the map.
+ */
+ zoomEnabled: PropTypes.bool,
+};
+
+const RNTMap = requireNativeComponent('RNTMap', MapView);
+
+export default MapView;
+```
+
+现在我们有了一个封装好的组件,还有了一些注释文档,用户使用起来也更方便了。注意我们现在把`requireNativeComponent`的第二个参数从 null 变成了用于封装的组件`MapView`。这使得 React Native 的底层框架可以检查原生属性和包装类的属性是否一致,来减少出现问题的可能。
+
+现在,让我们添加一个更复杂些的`region`属性。我们首先添加原生代码:
+
+```objectivec
+// RNTMapManager.m
+RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
+{
+ [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES];
+}
+```
+
+这段代码比刚才的一个简单的`BOOL`要复杂的多了。现在我们多了一个需要做类型转换的`MKCoordinateRegion`类型,还添加了一部分自定义的代码,这样当我们在 JS 里改变地图的可视区域的时候,视角会平滑地移动过去。在我们提供的函数体内,`json`代表了 JS 中传递的尚未解析的原始值。函数里还有一个`view`变量,使得我们可以访问到对应的视图实例。最后,还有一个`defaultView`对象,这样当 JS 给我们发送 null 的时候,可以把视图的这个属性重置回默认值。
+
+你可以为视图编写任何你所需要的转换函数——下面就是用 `RCTConvert` 实现的 `MKCoordinateRegion`。它使用了 ReactNative 中已经存在的 `RCTConvert+CoreLocation`:
+
+```objectivec
+// RNTMapManager.m
+
+#import "RCTConvert+Mapkit.h"
+
+// RCTConvert+Mapkit.h
+
+#import
+#import
+#import
+#import
+
+@interface RCTConvert (Mapkit)
+
++ (MKCoordinateSpan)MKCoordinateSpan:(id)json;
++ (MKCoordinateRegion)MKCoordinateRegion:(id)json;
+
+@end
+
+@implementation RCTConvert(MapKit)
+
++ (MKCoordinateSpan)MKCoordinateSpan:(id)json
+{
+ json = [self NSDictionary:json];
+ return (MKCoordinateSpan){
+ [self CLLocationDegrees:json[@"latitudeDelta"]],
+ [self CLLocationDegrees:json[@"longitudeDelta"]]
+ };
+}
+
++ (MKCoordinateRegion)MKCoordinateRegion:(id)json
+{
+ return (MKCoordinateRegion){
+ [self CLLocationCoordinate2D:json],
+ [self MKCoordinateSpan:json]
+ };
+}
+
+@end
+```
+
+这些转换函数被设计为可以安全的处理任何 JS 扔过来的 JSON:当有任何缺少的键或者其它问题发生的时候,显示一个“红屏”的错误提示。
+
+为了完成`region`属性的支持,我们还需要在`propTypes`里添加相应的说明(否则我们会立刻收到一个错误提示),然后就可以像使用其他属性一样使用了:
+
+```jsx
+// MapView.js
+
+MapView.propTypes = {
+ /**
+ * A Boolean value that determines whether the user may use pinch
+ * gestures to zoom in and out of the map.
+ */
+ zoomEnabled: PropTypes.bool,
+
+ /**
+ * 地图要显示的区域。
+ *
+ * 区域由中心点坐标和区域范围坐标来定义。
+ *
+ */
+ region: PropTypes.shape({
+ /**
+ * 地图中心点的坐标。
+ */
+ latitude: PropTypes.number.isRequired,
+ longitude: PropTypes.number.isRequired,
+
+ /**
+ * 最小/最大经、纬度间的距离。
+ *
+ */
+ latitudeDelta: PropTypes.number.isRequired,
+ longitudeDelta: PropTypes.number.isRequired,
+ }),
+};
+
+// MyApp.js
+
+render() {
+ const region = {
+ latitude: 37.48,
+ longitude: -122.16,
+ latitudeDelta: 0.1,
+ longitudeDelta: 0.1,
+ };
+ return (
+
+ );
+}
+```
+
+现在你可以看到 region 属性的整个结构已经加上了文档说明——将来可能我们会自动生成一些类似的代码,但目前还没有实现。
+
+有时候你的原生组件有一些特殊的属性希望导出,但并不希望它成为公开的接口。举个例子,`Switch`组件可能会有一个`onChange`属性用来传递原始的原生事件,然后导出一个`onValueChange`属性,这个属性在调用的时候会带上`Switch`的状态作为参数之一。这样的话你可能不希望原生专用的属性出现在 API 之中,也就不希望把它放到`propTypes`里。可是如果你不放的话,又会出现一个报错。解决方案就是带上额外的`nativeOnly`参数,像这样:
+
+```jsx
+const RCTSwitch = requireNativeComponent('RCTSwitch', Switch, {
+ nativeOnly: {onChange: true},
+});
+```
+
+## 事件
+
+现在我们已经有了一个原生地图组件,并且从 JS 可以很容易的控制它了。不过我们怎么才能处理来自用户的事件,譬如缩放操作或者拖动来改变可视区域?
+
+截至目前,我们从 manager 的 `-(UIView *)view` 方法返回了 `MKMapView` 实例。我们没法直接为 `MKMapView` 添加新的属性,所以我们只能创建一个 `MKMapView` 的子类用于我们自己的视图中。我们可以在这个子类中添加 `onRegionChange` 回调方法:
+
+```objectivec
+// RNTMapView.h
+
+#import
+
+#import
+
+@interface RNTMapView: MKMapView
+
+@property (nonatomic, copy) RCTBubblingEventBlock onRegionChange;
+
+@end
+
+// RNTMapView.m
+
+#import "RNTMapView.h"
+
+@implementation RNTMapView
+
+@end
+```
+
+需要注意的是,所有 `RCTBubblingEventBlock` 必须以 `on` 开头。然后在 `RNTMapManager`上声明一个事件处理函数属性,将其作为所暴露出来的所有视图的委托,并调用本地视图的事件处理将事件转发至 JS。
+
+```objectivec{9,17,31-48}
+// RNTMapManager.m
+
+#import
+#import
+
+#import "RNTMapView.h"
+#import "RCTConvert+Mapkit.h"
+
+@interface RNTMapManager : RCTViewManager
+@end
+
+@implementation RNTMapManager
+
+RCT_EXPORT_MODULE()
+
+RCT_EXPORT_VIEW_PROPERTY(zoomEnabled, BOOL)
+RCT_EXPORT_VIEW_PROPERTY(onRegionChange, RCTBubblingEventBlock)
+
+RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, MKMapView)
+{
+ [view setRegion:json ? [RCTConvert MKCoordinateRegion:json] : defaultView.region animated:YES];
+}
+
+- (UIView *)view
+{
+ RNTMapView *map = [RNTMapView new];
+ map.delegate = self;
+ return map;
+}
+
+#pragma mark MKMapViewDelegate
+
+- (void)mapView:(RNTMapView *)mapView regionDidChangeAnimated:(BOOL)animated
+{
+ if (!mapView.onRegionChange) {
+ return;
+ }
+
+ MKCoordinateRegion region = mapView.region;
+ mapView.onRegionChange(@{
+ @"region": @{
+ @"latitude": @(region.center.latitude),
+ @"longitude": @(region.center.longitude),
+ @"latitudeDelta": @(region.span.latitudeDelta),
+ @"longitudeDelta": @(region.span.longitudeDelta),
+ }
+ });
+}
+@end
+```
+
+在委托方法`-mapView:regionDidChangeAnimated:`中,根据对应的视图调用事件处理函数并传递区域数据。调用`onRegionChange`事件会触发 JavaScript 端的同名回调函数。这个回调会传递原生事件对象,然后我们通常都会在封装组件里来处理这个对象,以使 API 更简明:
+
+```jsx
+// MapView.js
+
+class MapView extends React.Component {
+ _onRegionChange = (event) => {
+ if (!this.props.onRegionChange) {
+ return;
+ }
+
+ // process raw event...
+ this.props.onRegionChange(event.nativeEvent);
+ }
+ render() {
+ return (
+
+ );
+ }
+}
+MapView.propTypes = {
+ /**
+ * Callback that is called continuously when the user is dragging the map.
+ */
+ onRegionChange: PropTypes.func,
+ ...
+};
+
+// MyApp.js
+
+class MyApp extends React.Component {
+ onRegionChange(event) {
+ // Do stuff with event.region.latitude, etc.
+ }
+
+ render() {
+ const region = {
+ latitude: 37.48,
+ longitude: -122.16,
+ latitudeDelta: 0.1,
+ longitudeDelta: 0.1,
+ };
+ return (
+
+ );
+ }
+}
+```
+
+## Handling multiple native views
+
+A React Native view can have more than one child view in the view tree eg.
+
+```jsx
+
+
+
+
+
+```
+
+In this example, the class `MyNativeView` is a wrapper for a `NativeComponent` and exposes methods, which will be called on the iOS platform. `MyNativeView` is defined in `MyNativeView.ios.js` and contains proxy methods of `NativeComponent`.
+
+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
+
+/>
+/>
+ { this.myNativeReference.callNativeMethod() }}/>
+
+```
+
+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`.
+
+`MyNativeView.ios.js` contains code as follow:
+
+```jsx
+class MyNativeView extends React.Component<> {
+ callNativeMethod = () => {
+ UIManager.dispatchViewManagerCommand(
+ ReactNative.findNodeHandle(this),
+ UIManager.getViewManagerConfig('RNCMyNativeView').Commands
+ .callNativeMethod,
+ []
+ );
+ };
+ render() {
+ return ;
+ }
+}
+```
+
+`callNativeMethod` is our custom iOS method which for example changes the `backgroundColor` which is exposed through `MyNativeView`. This method uses `UIManager.dispatchViewManagerCommand` which needs 3 parameters:
+
+- `(nonnull NSNumber \*)reactTag` - id of react view.
+- `commandID:(NSInteger)commandID` - Id of the native method that should be called
+- `commandArgs:(NSArray \*)commandArgs` - Args of the native method that we can pass from JS to native.
+
+`RNCMyNativeViewManager.m`
+
+```objectivec
+#import
+#import
+#import
+RCT_EXPORT_METHOD(callNativeMethod:(nonnull NSNumber*) reactTag) {
+ [self.bridge.uiManager addUIBlock:^(RCTUIManager *uiManager, NSDictionary *viewRegistry) {
+ NativeView *view = viewRegistry[reactTag];
+ if (!view || ![view isKindOfClass:[NativeView class]]) {
+ RCTLogError(@"Cannot find NativeView with tag #%@", reactTag);
+ return;
+ }
+ [view callNativeMethod];
+ }];
+}
+```
+
+Here the `callNativeMethod` is defined in the `RNCMyNativeViewManager.m` file and contains only one parameter which is `(nonnull NSNumber*) reactTag`. This exported function will find a particular view using `addUIBlock` which contains the `viewRegistry` parameter and returns the component based on `reactTag` allowing it to call the method on the correct component.
+
+## 样式
+
+因为我们所有的视图都是`UIView`的子类,大部分的样式属性应该直接就可以生效。但有一部分组件会希望使用自己定义的默认样式,例如`UIDatePicker`希望自己的大小是固定的。这个默认属性对于布局算法的正常工作来说很重要,但我们也希望在使用这个组件的时候可以覆盖这些默认的样式。`DatePickerIOS`实现这个功能的办法是通过封装一个拥有弹性样式的额外视图,然后在内层的视图上应用一个固定样式(通过原生传递来的常数生成):
+
+```jsx
+// DatePickerIOS.ios.js
+
+import { UIManager } from 'react-native';
+const RCTDatePickerIOSConsts = UIManager.RCTDatePicker.Constants;
+...
+ render: function() {
+ return (
+
+
+
+ );
+ }
+});
+
+const styles = StyleSheet.create({
+ rkDatePickerIOS: {
+ height: RCTDatePickerIOSConsts.ComponentHeight,
+ width: RCTDatePickerIOSConsts.ComponentWidth,
+ },
+});
+```
+
+常量`RCTDatePickerIOSConsts`在原生代码中导出,从一个组件的实际布局上获取到:
+
+```objectivec
+// RCTDatePickerManager.m
+
+- (NSDictionary *)constantsToExport
+{
+ UIDatePicker *dp = [[UIDatePicker alloc] init];
+ [dp layoutIfNeeded];
+
+ return @{
+ @"ComponentHeight": @(CGRectGetHeight(dp.frame)),
+ @"ComponentWidth": @(CGRectGetWidth(dp.frame)),
+ @"DatePickerModes": @{
+ @"time": @(UIDatePickerModeTime),
+ @"date": @(UIDatePickerModeDate),
+ @"datetime": @(UIDatePickerModeDateAndTime),
+ }
+ };
+}
+```
+
+本向导覆盖了包装原生组件所需了解的许多方面,不过你可能还有很多知识需要了解,譬如特殊的方式来插入和布局子视图。如果你想更深入了解,可以尝试阅读一些[源代码](https://github.com/facebook/react-native/blob/master/React/Views)。
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-android.md b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-android.md
new file mode 100644
index 00000000000..95be6ff1981
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-android.md
@@ -0,0 +1,1179 @@
+---
+id: native-modules-android
+title: Android 原生模块
+---
+
+import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecation.mdx'
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+
+
+欢迎来到 Android 的原生模块。请先阅读 [原生模块简介](native-modules-intro) 以了解原生模块的基本概念。
+
+## 创建一个 Calendar 原生模块
+
+在以下指南中,你将创建一个名为 `CalendarModule` 的原生模块,它允许你从 JavaScript 访问 Android 的日历 API。最终,你将能够从 JavaScript 中调用 `CalendarModule.createCalendarEvent('Dinner Party', 'My House');`,从而调用 Java/Kotlin 方法创建一个日历事件。
+
+### 设置
+
+要开始,请在 Android Studio 中打开 React Native 应用程序中的 Android 项目。你可以在 React Native 应用中找到 Android 项目的位置:
+
+
+
+ Image of where you can find your Android project
+
+
+我们建议使用 Android Studio 来编写你的原生代码。Android Studio 是一个为 Android 开发而构建的 IDE,使用它将帮助你快速解决代码语法错误等小问题。
+
+我们还建议启用 [Gradle Daemon](https://docs.gradle.org/2.9/userguide/gradle_daemon.html) 以加快你迭代 Java/Kotlin 代码时的构建速度。
+
+### 创建自定义原生模块文件
+
+第一步是在 `android/app/src/main/java/com/your-app-name/` 文件夹中创建 Java/Kotlin 文件(`CalendarModule.java` 或 `CalendarModule.kt`)。该 Java/Kotlin 文件将包含您的原生模块 Java/Kotlin 类。
+
+
+
+ Image of how to add the CalendarModuleClass
+
+
+然后添加如下代码:
+
+
+
+
+```java
+package com.your-apps-package-name; // replace your-apps-package-name with your app’s package name
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import java.util.Map;
+import java.util.HashMap;
+
+public class CalendarModule extends ReactContextBaseJavaModule {
+ CalendarModule(ReactApplicationContext context) {
+ super(context);
+ }
+}
+```
+
+
+
+
+```kotlin
+package com.your-apps-package-name; // replace your-apps-package-name with your app’s package name
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.bridge.ReactContext
+import com.facebook.react.bridge.ReactContextBaseJavaModule
+import com.facebook.react.bridge.ReactMethod
+
+class CalendarModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {...}
+```
+
+
+
+
+正如您所看到的,您的`CalendarModule`类继承自`ReactContextBaseJavaModule`类。对于安卓系统,Java/Kotlin 原生模块是用扩展了`ReactContextBaseJavaModule`并实现了 JavaScript 所需功能的类来编写的。
+
+值得注意的是,从技术上讲,Java/Kotlin 类只需要扩展`BaseJavaModule`类或实现`NativeModule`接口,才能被 React Native 视为原生模块。
+
+然而,我们建议您使用上面所示的`ReactContextBaseJavaModule`。`ReactContextBaseJavaModule`提供了`ReactApplicationContext`(RAC)的访问权限,这对于需要挂钩到活动生命周期方法的原生模块非常有用。使用`ReactContextBaseJavaModule`也将使您更容易在将来实现原生模块的类型安全性。为了实现原生模块类型安全性(将在未来版本中推出),React Native 会查看每个原生模块的 JavaScript 规范,并生成一个抽象基类,该基类扩展自`ReactContextBaseJavaModule`。
+
+### 模块名称
+
+所有 Android 平台上的 Java/Kotlin 原生模块都需要实现 `getName()` 方法。该方法返回一个字符串,代表了原生模块的名称。这样,原生模块就可以通过其名称在 JavaScript 中被访问。例如,在下面的代码片段中,`getName()` 返回 `"CalendarModule"`。
+
+
+
+
+```java
+// add to CalendarModule.java
+@Override
+public String getName() {
+ return "CalendarModule";
+}
+```
+
+
+
+
+```kotlin
+// add to CalendarModule.kt
+override fun getName() = "CalendarModule"
+```
+
+
+
+
+可以通过以下方式在 JS 中访问原生模块:
+
+```tsx
+const {CalendarModule} = ReactNative.NativeModules;
+```
+
+### 向 JavaScript 导出原生方法
+
+接下来,您需要在原生模块中添加一个方法,该方法可以创建日历事件,并可以在 JavaScript 中调用。所有打算从 JavaScript 调用的原生模块方法都必须使用`@ReactMethod`进行注解。
+
+为`CalendarModule`设置一个方法`createCalendarEvent()`,可以通过`CalendarModule.createCalendarEvent()`在 JS 中调用。目前,该方法将采用名称和位置作为字符串参数。参数类型选项将在稍后介绍。
+
+
+
+
+```java
+@ReactMethod
+public void createCalendarEvent(String name, String location) {
+}
+```
+
+
+
+
+```kotlin
+@ReactMethod fun createCalendarEvent(name: String, location: String) {}
+```
+
+
+
+
+在您从应用程序调用该方法时,请在该方法中添加一条调试日志以确认它已被调用。以下是如何从 Android 工具包中导入并使用[Log](https:// developer.android.com/reference/android/util/Log)类的示例:
+
+
+
+
+```java
+import android.util.Log;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location) {
+ Log.d("CalendarModule", "Create event called with name: " + name
+ + " and location: " + location);
+}
+```
+
+
+
+
+```kotlin
+import android.util.Log
+
+@ReactMethod
+fun createCalendarEvent(name: String, location: String) {
+ Log.d("CalendarModule", "Create event called with name: $name and location: $location")
+}
+```
+
+
+
+
+一旦您完成了原生模块的实现并将其与 JavaScript 连接起来,您便可以遵循[这些步骤](https://developer.android.com/studio/debug/am-logcat.html)查看应用程序的日志。
+
+### 同步方法
+
+您可以将 `isBlockingSynchronousMethod = true` 传递给原生方法,将其标记为同步方法。
+
+
+
+
+```java
+@ReactMethod(isBlockingSynchronousMethod = true)
+```
+
+
+
+
+```kotlin
+@ReactMethod(isBlockingSynchronousMethod = true)
+```
+
+
+
+
+就目前而言,我们并不建议这么做,因为以同步的方式调用方法可能会带来严重的性能损失,并且可能会给你的原生模块引入与线程相关的 bug。此外,请注意,如果你选择启用 `isBlockingSynchronousMethod`, 你的应用程序将无法再使用 Google Chrome 调试器。这是因为同步方法需要 JS VM 与应用程序共享内存。对于 Google Chrome 调试器而言,React Native 运行在 Google Chrome 中的 JS VM 内部,并通过 WebSockets 与移动设备进行异步通信。
+
+### 在 Android 上注册模块
+
+一旦编写了原生模块,就需要将其注册到 React Native 中。为此,你需要将你的原生模块添加到一个 `ReactPackage` 中,并将该 `ReactPackage` 注册到 React Native。在初始化过程中,React Native 会遍历所有包,并对于每个 `ReactPackage`,注册其中的每个原生模块。
+
+React Native 会调用 `ReactPackage` 的 `createNativeModules()` 方法,以获取要注册的原生模块列表。对于 Android 而言,如果一个模块未在 createNativeModules 中被实例化并返回,那么它就不会在 JavaScript 中可用。
+
+要将你的原生模块添加到 `ReactPackage` 中,首先在 `android/app/src/main/java/com/your-app-name/` 文件夹中创建一个新的 Java/Kotlin 类(`MyAppPackage.java` 或 `MyAppPackage.kt`),并实现 `ReactPackage` 接口:
+
+然后添加以下内容:
+
+
+
+
+```java
+package com.your-app-name; // replace your-app-name with your app’s name
+import com.facebook.react.ReactPackage;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.uimanager.ViewManager;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+public class MyAppPackage implements ReactPackage {
+
+ @Override
+ public List createViewManagers(ReactApplicationContext reactContext) {
+ return Collections.emptyList();
+ }
+
+ @Override
+ public List createNativeModules(
+ ReactApplicationContext reactContext) {
+ List modules = new ArrayList<>();
+
+ modules.add(new CalendarModule(reactContext));
+
+ return modules;
+ }
+
+}
+```
+
+
+
+
+```kotlin
+package com.your-app-name // replace your-app-name with your app’s name
+
+import android.view.View
+import com.facebook.react.ReactPackage
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.uimanager.ReactShadowNode
+import com.facebook.react.uimanager.ViewManager
+
+class MyAppPackage : ReactPackage {
+
+ override fun createViewManagers(
+ reactContext: ReactApplicationContext
+ ): MutableList>> = mutableListOf()
+
+ override fun createNativeModules(
+ reactContext: ReactApplicationContext
+ ): MutableList = listOf(CalendarModule(reactContext)).toMutableList()
+}
+```
+
+
+
+
+这个文件导入了你创建的原生模块`CalendarModule`。然后在`createNativeModules()`函数中实例化了`CalendarModule`并将其作为`NativeModules`列表返回以便注册。如果将来你添加更多原生模块,也可以在这里实例化它们并添加到返回的列表中。
+
+值得注意的是,这种注册原生模块的方式会在应用启动时主动地初始化所有原生模块,从而增加了应用的启动时间。你可以使用[TurboReactPackage](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/TurboReactPackage.java)作为替代方案。与返回已实例化的原生模块对象列表的`createNativeModules`不同,TurboReactPackage 实现了一个`getModule(String name, ReactApplicationContext rac)`方法,在需要时创建原生模块对象。目前实现 TurboReactPackage 有点复杂。除了实现`getModule()`方法外,你还必须实现一个`getReactModuleInfoProvider()`方法,该方法返回包可实例化的所有原生模块列表以及实例化它们的函数,示例[在此](https://github.com/facebook/react-native/blob/8ac467c51b94c82d81930b4802b2978c85539925/ReactAndroid/src/main/java/com/facebook/react/CoreModulesPackage.java#L86-L165)。再次说明,使用 TurboReactPackage 将使你的应用拥有更快的启动时间,但目前编写起来有些麻烦。所以如果你选择使用 TurboReactPackage,请小心谨慎。
+
+要注册`CalendarModule`包,你必须将`MyAppPackage`添加到 ReactNativeHost 的`getPackages()`方法返回的包列表中。打开`MainApplication.java`或`MainApplication.kt`文件,位于如下路径:`android/app/src/main/java/com/your-app-name/`。
+
+找到 ReactNativeHost 的`getPackages()`方法,并将你的包添加到`getPackages()`返回的包列表中。
+
+
+
+
+```java
+@Override
+ protected List getPackages() {
+ @SuppressWarnings("UnnecessaryLocalVariable")
+ List packages = new PackageList(this).getPackages();
+ // below MyAppPackage is added to the list of packages returned
+ packages.add(new MyAppPackage());
+ return packages;
+ }
+```
+
+
+
+
+```kotlin
+override fun getPackages(): List =
+ PackageList(this).packages.apply {
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // packages.add(new MyReactNativePackage());
+ add(MyAppPackage())
+ }
+```
+
+
+
+
+您已成功为 Android 注册了原生模块!
+
+### 测试已构建的内容
+
+此时,您已为 Android 原生模块搭建了基本的脚手架。通过在 JavaScript 中访问原生模块并调用它导出的方法来测试一下。
+
+在应用中找到一个添加调用原生模块的 createCalendarEvent()方法的位置。下面是一个示例组件 NewModuleButton,您可以在应用中添加它。您可以在 NewModuleButton 的 onPress()函数中调用原生模块。
+
+```tsx
+import React from 'react';
+import {NativeModules, Button} from 'react-native';
+
+const NewModuleButton = () => {
+ const onPress = () => {
+ console.log('We will invoke the native module here!');
+ };
+
+ return (
+
+ );
+};
+
+export default NewModuleButton;
+```
+
+为了从 JavaScript 访问您的原生模块,您需要先从 React Native 导入`NativeModules`:
+
+```tsx
+import {NativeModules} from 'react-native';
+```
+
+然后您就可以从`NativeModules`访问`CalendarModule`原生模块了。
+
+```tsx
+const {CalendarModule} = NativeModules;
+```
+
+现在您有了可用的 CalendarModule 原生模块,就可以调用您的原生方法`createCalendarEvent()`了。下面是在`NewModuleButton`的`onPress()`方法中添加的代码:
+
+```tsx
+const onPress = () => {
+ CalendarModule.createCalendarEvent('testName', 'testLocation');
+};
+```
+
+最后一步是重新构建 React Native 应用程序,以便您可以使用最新的原生代码(包括您新的原生模块!)。在您的 react native 应用程序所在的命令行中,运行以下命令:
+
+
+
+
+```shell
+npm run android
+```
+
+
+
+
+```shell
+yarn android
+```
+
+
+
+
+### 在迭代过程中构建
+
+在学习这些指南并对您的原生模块进行迭代的过程中,您需要对应用程序进行原生重建,以从 JavaScript 访问您最新的更改。这是因为您编写的代码位于应用程序的原生部分。虽然 React Native 的 metro bundler 可以监视 JavaScript 中的更改并为您实时重建,但它不会对原生代码进行操作。因此,如果您想测试最新的原生更改,需要使用上述命令进行重建。
+
+### 小结 ✨
+
+现在,您应该能够在应用程序中调用原生模块上的`createCalendarEvent()`方法。在我们的示例中,这是通过按下`NewModuleButton`来实现的。您可以通过查看在`createCalendarEvent()`方法中设置的日志来确认这一点。您可以按照[这些步骤](https://developer.android.com/studio/debug/am-logcat.html)在应用中查看 ADB 日志。然后,您应该能够搜索您的`Log.d`消息(在我们的示例中是"Create event called with name: testName and location: testLocation"),并在每次调用原生模块方法时看到您的消息被记录。
+
+
+
+ Image of ADB logs in Android Studio
+
+
+在这一点上,您已经创建了一个 Android 原生模块,并从您的 React Native 应用程序中的 JavaScript 调用了它的原生方法。您可以继续学习诸如原生模块方法可用的参数类型以及如何设置回调和承诺之类的内容。
+
+## 超越日历原生模块
+
+### 更好的原生模块导出
+
+从上面的 `NativeModules` 导入您的原生模块是有点麻烦的。
+
+为了让您原生模块的消费者无需每次都这样访问您的原生模块,您可以为该模块创建一个 JavaScript 包装器。创建一个名为 `CalendarModule.js` 的新 JavaScript 文件,其中包含以下内容:
+
+```tsx
+/**
+* 这将原生 CalendarModule 模块作为 JS 模块暴露。它有一个名为 'createCalendarEvent' 的函数,该函数接受以下参数:
+
+* 1. String name: 表示事件名称的字符串
+* 2. String location: 表示事件位置的字符串
+*/
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+export default CalendarModule;
+```
+
+此 JavaScript 文件也将成为您添加任何 JavaScript 端功能的绝佳位置。例如,如果您使用 TypeScript 等类型系统,可以在此处为您的原生模块添加类型注释。虽然 React Native 目前还不支持从原生到 JS 的类型安全性,但您所有的 JS 代码都将是类型安全的。这样做也将使您将来更容易切换到类型安全的原生模块。下面是为 CalendarModule 添加类型安全性的示例:
+
+```tsx
+/**
+ * 这个模块以 JS 模块的方式暴露了原生 CalendarModule。它有一个名为 "createCalendarEvent" 的函数,接受以下两个参数:
+ *
+ * 1. String name: 代表事件名称的字符串
+ * 2. String location: 代表事件地点的字符串
+ */
+import {NativeModules} from 'react-native';
+const {CalendarModule} = NativeModules;
+interface CalendarInterface {
+ createCalendarEvent(name: string, location: string): void;
+}
+export default CalendarModule as CalendarInterface;
+```
+
+在其他 JavaScript 文件中,你可以如下引入原生模块并调用它的方法:
+
+```tsx
+import CalendarModule from './CalendarModule';
+CalendarModule.createCalendarEvent('foo', 'bar');
+```
+
+> 这假设你导入 `CalendarModule` 的位置与 `CalendarModule.js` 在同一层级目录。如有必要,请相应更新导入路径。
+
+### 参数类型
+
+当在 JavaScript 中调用原生模块方法时,React Native 会将参数从 JS 对象转换为对应的 Java/Kotlin 对象类型。例如,如果你的 Java 原生模块方法接受一个 double 类型,在 JS 中你需要用数字来调用该方法。React Native 会为你处理转换。下面列出了原生模块方法支持的参数类型以及它们在 JavaScript 中对应的等价类型。
+
+| Java | Kotlin | JavaScript |
+| ------------- | ------------- | ---------- |
+| Boolean | Boolean | ?boolean |
+| boolean | | boolean |
+| Double | Double | ?number |
+| double | | number |
+| String | String | string |
+| Callback | Callback | Function |
+| Promise | Promise | Promise |
+| ReadableMap | ReadableMap | Object |
+| ReadableArray | ReadableArray | Array |
+
+> 以下类型目前虽然受支持,但在 TurboModules 中将不再支持,请避免使用:
+>
+> - Integer Java/Kotlin -> ?number
+> - Float Java/Kotlin -> ?number
+> - int Java -> number
+> - float Java -> number
+
+对于上面未列出的参数类型,你需要自行处理类型转换。例如,在 Android 中,Date 类型的转换并不是开箱即用的。你可以在原生方法中自己处理 Date 类型的转换,如下所示:
+
+
+
+
+```java
+ String dateFormat = "yyyy-MM-dd";
+ SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
+ Calendar eStartDate = Calendar.getInstance();
+ try {
+ eStartDate.setTime(sdf.parse(startDate));
+ }
+
+```
+
+
+
+
+```kotlin
+ val dateFormat = "yyyy-MM-dd"
+ val sdf = SimpleDateFormat(dateFormat, Locale.US)
+ val eStartDate = Calendar.getInstance()
+ try {
+ sdf.parse(startDate)?.let {
+ eStartDate.time = it
+ }
+ }
+```
+
+
+
+
+### 导出常量
+
+一个原生模块可以通过实现在 JavaScript 中可用的原生方法 `getConstants()` 来导出常量。接下来,您将实现 `getConstants()` 并返回一个包含 `DEFAULT_EVENT_NAME` 常量的映射,您可以在 JavaScript 中访问该常量:
+
+
+
+
+```java
+@Override
+public Map getConstants() {
+ final Map constants = new HashMap<>();
+ constants.put("DEFAULT_EVENT_NAME", "New Event");
+ return constants;
+}
+```
+
+
+
+
+```kotlin
+override fun getConstants(): MutableMap =
+ hashMapOf("DEFAULT_EVENT_NAME" to "New Event")
+```
+
+
+
+
+然后,可以在 JS 中通过在原生模块上调用`getConstants`来访问该常量:
+
+```tsx
+const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);
+```
+
+理论上可以直接从原生模块对象访问在`getConstants()`中导出的常量。但这种做法将来不再受支持,因此我们鼓励社区转而采用上述方式,以避免将来不得不迁移代码。
+
+> 目前,常量仅在初始化时导出,因此如果您在运行时更改了 getConstants 的值,它不会影响 JavaScript 环境。这种情况将随着 Turbomodules 而改变。使用 Turbomodules 后,`getConstants()`将成为一个常规的原生模块方法,每次调用都会触及原生端。
+
+### 回调函数
+
+原生模块还支持一种独特的参数类型:回调函数。回调函数用于将数据从 Java/Kotlin 异步传递到 JavaScript,同时也可用于从原生端异步执行 JavaScript 代码。
+
+为了在原生模块方法中加入回调函数,首先要引入`Callback`接口,然后将`Callback`类型的参数添加到你的原生模块方法中。目前使用回调参数还有一些细微差别,不过这些将在 TurboModules 中得到解决。目前,你的函数参数只能有两个回调函数——一个成功回调和一个失败回调。另外,如果原生模块方法调用的最后一个参数是函数,则将被视为成功回调;如果倒数第二个参数是函数,则被视为失败回调。
+
+
+
+
+```java
+import com.facebook.react.bridge.Callback;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location, Callback callBack) {
+}
+```
+
+
+
+
+```kotlin
+import com.facebook.react.bridge.Callback
+
+@ReactMethod fun createCalendarEvent(name: String, location: String, callback: Callback) {}
+```
+
+
+
+
+你可以在 Java/Kotlin 方法中调用回调函数,提供任何需要传递给 JavaScript 的数据。请注意,你只能从原生代码传递可序列化的数据到 JavaScript。如果需要传递原生对象,你可以使用`WriteableMaps`,如果需要使用集合,可以使用`WritableArrays`。还需要强调的是,回调函数不会在原生函数完成后立即被调用。下面是之前创建的一个事件 ID,将被传递给回调函数。
+
+
+
+
+```java
+ @ReactMethod
+ public void createCalendarEvent(String name, String location, Callback callBack) {
+ Integer eventId = ...
+ callBack.invoke(eventId);
+ }
+```
+
+
+
+
+```kotlin
+ @ReactMethod
+ fun createCalendarEvent(name: String, location: String, callback: Callback) {
+ val eventId = ...
+ callback.invoke(eventId)
+ }
+```
+
+
+
+
+然后就可以在 JavaScript 中使用以下方法:
+
+```tsx
+const onPress = () => {
+ CalendarModule.createCalendarEvent(
+ 'Party',
+ 'My House',
+ eventId => {
+ console.log(`Created a new event with id ${eventId}`);
+ },
+ );
+};
+```
+
+另一个需要注意的重要细节是,原生模块方法只能调用一次回调函数,这意味着你可以调用成功回调或失败回调,但不能两者兼得,而且每个回调最多只能被调用一次。不过,原生模块可以存储回调函数,并在以后调用它。
+
+处理回调错误有两种方法。第一种是遵循 Node 的惯例,将传给回调函数的第一个参数视为错误对象。
+
+
+
+
+```java
+ @ReactMethod
+ public void createCalendarEvent(String name, String location, Callback callBack) {
+ Integer eventId = ...
+ callBack.invoke(null, eventId);
+ }
+```
+
+
+
+
+```kotlin
+ @ReactMethod
+ fun createCalendarEvent(name: String, location: String, callback: Callback) {
+ val eventId = ...
+ callback.invoke(null, eventId)
+ }
+```
+
+
+
+
+在 JavaScript 中,你可以先检查第一个参数,看看是否传递了错误:
+
+```tsx
+const onPress = () => {
+ CalendarModule.createCalendarEvent(
+ 'testName',
+ 'testLocation',
+ (error, eventId) => {
+ if (error) {
+ console.error(`Error found! ${error}`);
+ }
+ console.log(`event id ${eventId} returned`);
+ },
+ );
+};
+```
+
+另一种选择是使用 onSuccess 和 onFailure 回调函数:
+
+
+
+
+```java
+@ReactMethod
+public void createCalendarEvent(String name, String location, Callback myFailureCallback, Callback mySuccessCallback) {
+}
+```
+
+
+
+
+```kotlin
+@ReactMethod
+ fun createCalendarEvent(
+ name: String,
+ location: String,
+ myFailureCallback: Callback,
+ mySuccessCallback: Callback
+ ) {}
+```
+
+
+
+
+在 JavaScript 中,您可以为错误和成功响应分别添加单独的回调函数:
+
+```tsx
+const onPress = () => {
+ CalendarModule.createCalendarEvent(
+ 'testName',
+ 'testLocation',
+ error => {
+ console.error(`Error found! ${error}`);
+ },
+ eventId => {
+ console.log(`event id ${eventId} returned`);
+ },
+ );
+};
+```
+
+### Promises
+
+原生模块也可以实现[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise)承诺,这有助于简化您的 JavaScript 代码,尤其是在使用 ES2016 的[async/await](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/async_function)语法时。当原生模块 Java/Kotlin 方法的最后一个参数为 Promise 时,对应的 JS 方法将返回一个 JS Promise 对象。
+
+用 Promise 重构上述代码,代码如下:
+
+
+
+
+```java
+import com.facebook.react.bridge.Promise;
+
+@ReactMethod
+public void createCalendarEvent(String name, String location, Promise promise) {
+ try {
+ Integer eventId = ...
+ promise.resolve(eventId);
+ } catch(Exception e) {
+ promise.reject("Create Event Error", e);
+ }
+}
+```
+
+
+
+
+```kotlin
+import com.facebook.react.bridge.Promise
+
+@ReactMethod
+fun createCalendarEvent(name: String, location: String, promise: Promise) {
+ try {
+ val eventId = ...
+ promise.resolve(eventId)
+ } catch (e: Throwable) {
+ promise.reject("Create Event Error", e)
+ }
+}
+```
+
+
+
+
+> 类似于回调,原生模块方法可以拒绝或解决一个 Promise(但不能两者都做),并且最多只能执行一次。这意味着您可以调用成功回调或失败回调, 但不能两者都调用,且每个回调最多只能被调用一次。不过,原生模块可以存储回调并稍后调用它。
+
+该方法的 JavaScript 对应部分返回一个 Promise。这意味着您可以在异步函数中使用 `await` 关键字调用它并等待其结果:
+
+```tsx
+const onSubmit = async () => {
+ try {
+ const eventId = await CalendarModule.createCalendarEvent(
+ 'Party',
+ 'My House',
+ );
+ console.log(`Created a new event with id ${eventId}`);
+ } catch (e) {
+ console.error(e);
+ }
+};
+```
+
+reject 方法接受以下几种参数组合:
+
+
+
+
+```java
+String code, String message, WritableMap userInfo, Throwable throwable
+```
+
+
+
+
+```kotlin
+code: String, message: String, userInfo: WritableMap, throwable: Throwable
+```
+
+
+
+
+更多详细内容,您可以在[这里](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/bridge/Promise.java)查阅 `Promise.java` 接口。如果未提供 `userInfo`,React Native 会将其设置为 null。对于其余参数,React Native 将使用默认值。`message` 参数提供了显示在错误调用堆栈顶部的错误 `message`。以下是在 JavaScript 中显示的错误消息示例,该消息来自 Java/Kotlin 中的以下 reject 调用。
+
+Java/Kotlin 的 reject 调用:
+
+
+
+
+```java
+promise.reject("Create Event error", "Error parsing date", e);
+```
+
+
+
+
+```kotlin
+promise.reject("Create Event error", "Error parsing date", e)
+```
+
+
+
+
+在 React Native 应用中,如果 promise 被拒绝时,会抛出如下错误信息:
+
+
+
+ Image of error message
+
+
+### 向 JavaScript 发送事件
+
+原生模块无需直接调用即可向 JavaScript 发送事件信号。例如,您可能需要提醒 JavaScript 某项即将发生的原生 Android 日历应用程序日历事件。最简单的方式是使用从 ReactContext 中获取的 RCTDeviceEventEmitter,如下代码片段所示。
+
+
+
+
+```java
+...
+import com.facebook.react.modules.core.DeviceEventManagerModule;
+import com.facebook.react.bridge.WritableMap;
+import com.facebook.react.bridge.Arguments;
+...
+private void sendEvent(ReactContext reactContext,
+ String eventName,
+ @Nullable WritableMap params) {
+ reactContext
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
+ .emit(eventName, params);
+}
+
+private int listenerCount = 0;
+
+@ReactMethod
+public void addListener(String eventName) {
+ if (listenerCount == 0) {
+ // Set up any upstream listeners or background tasks as necessary
+ }
+
+ listenerCount += 1;
+}
+
+@ReactMethod
+public void removeListeners(Integer count) {
+ listenerCount -= count;
+ if (listenerCount == 0) {
+ // Remove upstream listeners, stop unnecessary background tasks
+ }
+}
+...
+WritableMap params = Arguments.createMap();
+params.putString("eventProperty", "someValue");
+...
+sendEvent(reactContext, "EventReminder", params);
+```
+
+
+
+
+```kotlin
+...
+import com.facebook.react.bridge.WritableMap
+import com.facebook.react.bridge.Arguments
+import com.facebook.react.modules.core.DeviceEventManagerModule
+...
+
+private fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) {
+ reactContext
+ .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
+ .emit(eventName, params)
+}
+
+private var listenerCount = 0
+
+@ReactMethod
+fun addListener(eventName: String) {
+ if (listenerCount == 0) {
+ // Set up any upstream listeners or background tasks as necessary
+ }
+
+ listenerCount += 1
+}
+
+@ReactMethod
+fun removeListeners(count: Int) {
+ listenerCount -= count
+ if (listenerCount == 0) {
+ // Remove upstream listeners, stop unnecessary background tasks
+ }
+}
+...
+val params = Arguments.createMap().apply {
+ putString("eventProperty", "someValue")
+}
+...
+sendEvent(reactContext, "EventReminder", params)
+```
+
+
+
+
+JavaScript 模块可通过在 [NativeEventEmitter](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/EventEmitter/NativeEventEmitter.js) 类上调用 `addListener` 方法来注册接收事件。
+
+```tsx
+import {NativeEventEmitter, NativeModules} from 'react-native';
+...
+useEffect(() => {
+ const eventEmitter = new NativeEventEmitter(NativeModules.ToastExample);
+ let eventListener = eventEmitter.addListener('EventReminder', event => {
+ console.log(event.eventProperty) // "someValue"
+ });
+
+ // Removes the listener once unmounted
+ return () => {
+ eventListener.remove();
+ };
+ }, []);
+```
+
+### 从 startActivityForResult 获取结果
+
+如果你想从使用`startActivityForResult`启动的 Activity 中获取结果,需要监听`onActivityResult`。为此,你必须扩展`BaseActivityEventListener`或实现`ActivityEventListener`。前者更可取,因为它更有弹性应对 API 变化。然后,你需要在模块的构造函数中注册监听器,就像这样:
+
+
+
+
+```java
+reactContext.addActivityEventListener(mActivityResultListener);
+```
+
+
+
+
+```kotlin
+reactContext.addActivityEventListener(mActivityResultListener);
+```
+
+
+
+
+现在你可以通过实现以下方法来监听 `onActivityResult` 事件:
+
+
+
+
+```java
+@Override
+public void onActivityResult(
+ final Activity activity,
+ final int requestCode,
+ final int resultCode,
+ final Intent intent) {
+ // Your logic here
+}
+```
+
+
+
+
+```kotlin
+override fun onActivityResult(
+ activity: Activity?,
+ requestCode: Int,
+ resultCode: Int,
+ intent: Intent?
+) {
+ // Your logic here
+}
+```
+
+
+
+
+让我们实现一个基本的图像选择器来演示这一点。该图像选择器将向 JavaScript 暴露方法 `pickImage`,调用该方法时会返回图像路径。
+
+
+
+
+```kotlin
+public class ImagePickerModule extends ReactContextBaseJavaModule {
+
+ private static final int IMAGE_PICKER_REQUEST = 1;
+ private static final String E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST";
+ private static final String E_PICKER_CANCELLED = "E_PICKER_CANCELLED";
+ private static final String E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER";
+ private static final String E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND";
+
+ private Promise mPickerPromise;
+
+ private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {
+
+ @Override
+ public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
+ if (requestCode == IMAGE_PICKER_REQUEST) {
+ if (mPickerPromise != null) {
+ if (resultCode == Activity.RESULT_CANCELED) {
+ mPickerPromise.reject(E_PICKER_CANCELLED, "Image picker was cancelled");
+ } else if (resultCode == Activity.RESULT_OK) {
+ Uri uri = intent.getData();
+
+ if (uri == null) {
+ mPickerPromise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found");
+ } else {
+ mPickerPromise.resolve(uri.toString());
+ }
+ }
+
+ mPickerPromise = null;
+ }
+ }
+ }
+ };
+
+ ImagePickerModule(ReactApplicationContext reactContext) {
+ super(reactContext);
+
+ // Add the listener for `onActivityResult`
+ reactContext.addActivityEventListener(mActivityEventListener);
+ }
+
+ @Override
+ public String getName() {
+ return "ImagePickerModule";
+ }
+
+ @ReactMethod
+ public void pickImage(final Promise promise) {
+ Activity currentActivity = getCurrentActivity();
+
+ if (currentActivity == null) {
+ promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist");
+ return;
+ }
+
+ // Store the promise to resolve/reject when picker returns data
+ mPickerPromise = promise;
+
+ try {
+ final Intent galleryIntent = new Intent(Intent.ACTION_PICK);
+
+ galleryIntent.setType("image/*");
+
+ final Intent chooserIntent = Intent.createChooser(galleryIntent, "Pick an image");
+
+ currentActivity.startActivityForResult(chooserIntent, IMAGE_PICKER_REQUEST);
+ } catch (Exception e) {
+ mPickerPromise.reject(E_FAILED_TO_SHOW_PICKER, e);
+ mPickerPromise = null;
+ }
+ }
+}
+```
+
+
+
+
+```kotlin
+class ImagePickerModule(reactContext: ReactApplicationContext) :
+ ReactContextBaseJavaModule(reactContext) {
+
+ private var pickerPromise: Promise? = null
+
+ private val activityEventListener =
+ object : BaseActivityEventListener() {
+ override fun onActivityResult(
+ activity: Activity?,
+ requestCode: Int,
+ resultCode: Int,
+ intent: Intent?
+ ) {
+ if (requestCode == IMAGE_PICKER_REQUEST) {
+ pickerPromise?.let { promise ->
+ when (resultCode) {
+ Activity.RESULT_CANCELED ->
+ promise.reject(E_PICKER_CANCELLED, "Image picker was cancelled")
+ Activity.RESULT_OK -> {
+ val uri = intent?.data
+
+ uri?.let { promise.resolve(uri.toString())}
+ ?: promise.reject(E_NO_IMAGE_DATA_FOUND, "No image data found")
+ }
+ }
+
+ pickerPromise = null
+ }
+ }
+ }
+ }
+
+ init {
+ reactContext.addActivityEventListener(activityEventListener)
+ }
+
+ override fun getName() = "ImagePickerModule"
+
+ @ReactMethod
+ fun pickImage(promise: Promise) {
+ val activity = currentActivity
+
+ if (activity == null) {
+ promise.reject(E_ACTIVITY_DOES_NOT_EXIST, "Activity doesn't exist")
+ return
+ }
+
+ pickerPromise = promise
+
+ try {
+ val galleryIntent = Intent(Intent.ACTION_PICK).apply { type = "image\/*" }
+
+ val chooserIntent = Intent.createChooser(galleryIntent, "Pick an image")
+
+ activity.startActivityForResult(chooserIntent, IMAGE_PICKER_REQUEST)
+ } catch (t: Throwable) {
+ pickerPromise?.reject(E_FAILED_TO_SHOW_PICKER, t)
+ pickerPromise = null
+ }
+ }
+
+ companion object {
+ const val IMAGE_PICKER_REQUEST = 1
+ const val E_ACTIVITY_DOES_NOT_EXIST = "E_ACTIVITY_DOES_NOT_EXIST"
+ const val E_PICKER_CANCELLED = "E_PICKER_CANCELLED"
+ const val E_FAILED_TO_SHOW_PICKER = "E_FAILED_TO_SHOW_PICKER"
+ const val E_NO_IMAGE_DATA_FOUND = "E_NO_IMAGE_DATA_FOUND"
+ }
+}
+```
+
+
+
+
+### 监听生命周期事件
+
+监听如 `onResume`、`onPause` 等活动的生命周期事件,跟实现 `ActivityEventListener` 的方式非常相似。该模块必须实现 `LifecycleEventListener`。然后,你需要在模块的构造函数中注册一个监听器,就像这样:
+
+
+
+
+```java
+reactContext.addLifecycleEventListener(this);
+```
+
+
+
+
+```kotlin
+reactContext.addLifecycleEventListener(this)
+```
+
+
+
+
+现在,通过实现以下方法,您可以监听活动的生命周期事件:
+
+
+
+
+```java
+@Override
+public void onHostResume() {
+ // Activity `onResume`
+}
+@Override
+public void onHostPause() {
+ // Activity `onPause`
+}
+@Override
+public void onHostDestroy() {
+ // Activity `onDestroy`
+}
+```
+
+
+
+
+```kotlin
+override fun onHostResume() {
+ // Activity `onResume`
+}
+
+override fun onHostPause() {
+ // Activity `onPause`
+}
+
+override fun onHostDestroy() {
+ // Activity `onDestroy`
+}
+```
+
+
+
+
+### 线程管理
+
+截至目前,在 Android 系统上,所有原生模块的异步方法都在同一个线程上执行。原生模块不应对它们被调用所在的线程作任何假设,因为当前的分配方式在未来可能会发生变化。如果需要进行阻塞调用,则应将繁重工作分派到内部管理的工作线程,并从那里分发任何回调。
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-intro.md b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-intro.md
new file mode 100644
index 00000000000..4d3f10bd3df
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-intro.md
@@ -0,0 +1,30 @@
+---
+id: native-modules-intro
+title: 原生模块简介
+---
+
+import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecation.mdx'
+
+
+
+有时候 App 需要访问平台 API,但 React Native 可能还没有相应的模块包装;或者你需要复用一些 Java 代码,而不是用 Javascript 重新实现一遍;又或者你需要实现某些高性能的、多线程的代码,譬如图片处理、数据库、或者各种高级扩展等等。
+
+我们把 React Native 设计为可以在其基础上编写真正的原生代码,并且可以访问平台所有的能力。这是一个相对高级的特性,我们并不认为它应当在日常开发的过程中经常出现,但具备这样的能力是很重要的。如果 React Native 还不支持某个你需要的原生特性,你应当可以自己实现该特性的封装。
+
+## 创建原生模块
+
+有多种方法可以为您的 React Native 应用程序编写原生模块:
+
+1. 创建一个可在您的 React Native 应用程序中导入的原生库。阅读[创建原生库](local-library-setup)指南以了解更多信息。
+2. 直接在您的 React Native 应用程序的 iOS / Android 项目中
+3. 作为一个 NPM 包,可以被您/其他 React Native 应用程序作为依赖项安装。
+
+本指南将首先介绍如何直接在 React Native 应用程序内实现原生模块。但是,在以下指南中构建的原生模块可以作为 NPM 包进行分发。如果您有兴趣这样做,请查看[设置为 NPM 包的原生模块](native-modules-setup)指南。
+
+## 教程
+
+在接下来的部分中,我们将带您了解如何在 React Native 应用程序内直接构建一个原生模块的指南。作为一个先决条件,您需要一个 React Native 应用程序来工作。如果您还没有,可以按照[这里](getting-started)的步骤设置一个 React Native 应用程序。
+
+想象一下,您想在 React Native 应用程序内的 JavaScript 中访问 iOS/Android 原生日历 API,以创建日历事件。React Native 没有公开与原生日历库通信的 JavaScript API。然而,通过原生模块,您可以编写与原生日历 API 通信的原生代码。然后您可以在 React Native 应用程序中的 JavaScript 里调用该原生代码。
+
+在接下来的部分中,您将为[Android](native-modules-android)和[iOS](native-modules-ios)创建这样一个 Calendar 原生模块。
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-ios.md b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-ios.md
new file mode 100644
index 00000000000..721be3757ec
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-ios.md
@@ -0,0 +1,632 @@
+---
+id: native-modules-ios
+title: iOS 原生模块
+---
+
+import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecation.mdx'
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+
+
+欢迎阅读 iOS 原生模块指南。请先阅读[原生模块简介](native-modules-intro)以了解原生模块的基本概念。
+
+## 创建一个日历原生模块
+
+在本指南中,你将创建一个名为 `CalendarModule` 的原生模块,使你能够从 JavaScript 访问 Apple 的日历 API。最终你将能够从 JavaScript 调用 `CalendarModule.createCalendarEvent('Dinner Party', 'My House');`,从而触发一个创建日历事件的原生方法。
+
+### 环境设置
+
+首先,在 Xcode 中打开你的 React Native 应用中的 iOS 项目。你可以在 React Native 应用中找到 iOS 项目:
+
+
+
+ 查找 iOS 项目的位置
+
+
+我们推荐使用 Xcode 来编写原生代码。Xcode 是为 iOS 开发而构建的,使用它可以帮助你快速解决代码语法等小错误。
+
+### 创建自定义原生模块文件
+
+第一步是创建我们的主自定义原生模块头文件和实现文件。创建一个名为 `RCTCalendarModule.h` 的新文件
+
+
+
+ 在与 AppDelegate 相同的文件夹中创建自定义原生模块文件
+
+
+并添加以下内容:
+
+```objectivec
+// RCTCalendarModule.h
+#import
+@interface RCTCalendarModule : NSObject
+@end
+
+```
+
+你可以使用任何适合你正在构建的原生模块的名称。将类命名为 `RCTCalendarModule` 是因为你正在创建一个日历原生模块。由于 ObjC 不像 Java 或 C++ 那样有语言级别的命名空间支持,惯例是在类名前添加一个子字符串。这可以是你的应用程序名称或基础设施名称的缩写。在本例中,RCT 代表 React。
+
+如下所示,CalendarModule 类实现了 `RCTBridgeModule` 协议。原生模块是一个实现了 `RCTBridgeModule` 协议的 Objective-C 类。
+
+接下来,让我们开始实现原生模块。在 Xcode 中使用 Cocoa Touch Class 创建对应的实现文件 `RCTCalendarModule.m`,放在同一个文件夹中,并包含以下内容:
+
+```objectivec
+// RCTCalendarModule.m
+#import "RCTCalendarModule.h"
+
+@implementation RCTCalendarModule
+
+// To export a module named RCTCalendarModule
+RCT_EXPORT_MODULE();
+
+@end
+
+```
+
+### 模块名称
+
+目前,你的 `RCTCalendarModule.m` 原生模块只包含一个 `RCT_EXPORT_MODULE` 宏,它会导出原生模块类并将其注册到 React Native。`RCT_EXPORT_MODULE` 宏还接受一个可选参数,指定模块在 JavaScript 代码中可访问的名称。
+
+这个参数不是字符串字面量。在下面的示例中,传递的是 `RCT_EXPORT_MODULE(CalendarModuleFoo)`,而不是 `RCT_EXPORT_MODULE("CalendarModuleFoo")`。
+
+```objectivec
+// To export a module named CalendarModuleFoo
+RCT_EXPORT_MODULE(CalendarModuleFoo);
+```
+
+然后可以在 JS 中这样访问原生模块:
+
+```tsx
+const {CalendarModuleFoo} = ReactNative.NativeModules;
+```
+
+如果你不指定名称,JavaScript 模块名将与 Objective-C 类名匹配,但会移除任何 "RCT" 或 "RK" 前缀。
+
+让我们按照下面的示例,不带任何参数调用 `RCT_EXPORT_MODULE`。因此,模块将以 `CalendarModule` 的名称暴露给 React Native,因为这是移除了 RCT 前缀后的 Objective-C 类名。
+
+```objectivec
+// Without passing in a name this will export the native module name as the Objective-C class name with "RCT" removed
+RCT_EXPORT_MODULE();
+```
+
+然后可以在 JS 中这样访问原生模块:
+
+```tsx
+const {CalendarModule} = ReactNative.NativeModules;
+```
+
+### 向 JavaScript 导出原生方法
+
+除非明确告知,否则 React Native 不会将原生模块中的任何方法暴露给 JavaScript。这可以使用 `RCT_EXPORT_METHOD` 宏来完成。在 `RCT_EXPORT_METHOD` 宏中编写的方法是异步的,因此返回类型始终为 void。为了将 `RCT_EXPORT_METHOD` 方法的结果传递给 JavaScript,你可以使用回调或触发事件(下文会介绍)。让我们使用 `RCT_EXPORT_METHOD` 宏为 `CalendarModule` 原生模块设置一个原生方法。将其命名为 `createCalendarEvent()`,暂时让它接受 name 和 location 两个字符串参数。参数类型选项稍后会介绍。
+
+```objectivec
+RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
+{
+}
+```
+
+:::note
+请注意,使用 TurboModules 时将不再需要 `RCT_EXPORT_METHOD` 宏,除非你的方法依赖于 RCT 参数转换(参见下面的参数类型)。最终 React Native 将移除 `RCT_EXPORT_MACRO`,因此我们不鼓励使用 `RCTConvert`。相反,你可以在方法体内进行参数转换。
+:::
+
+在你完善 `createCalendarEvent()` 方法的功能之前,先在方法中添加一个控制台日志,这样你就可以从 React Native 应用中的 JavaScript 确认它已被调用。使用 React 的 `RCTLog` API。让我们在文件顶部导入该头文件,然后添加日志调用。
+
+```objectivec
+#import
+RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)name location:(NSString *)location)
+{
+ RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);
+}
+```
+
+### 同步方法
+
+你可以使用 `RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD` 来创建同步的原生方法。
+
+```objectivec
+RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getName)
+{
+return [[UIDevice currentDevice] name];
+}
+```
+
+该方法的返回类型必须是对象类型 (id),并且应该可以序列化为 JSON。这意味着该方法只能返回 nil 或 JSON 值(例如 NSNumber、NSString、NSArray、NSDictionary)。
+
+目前,我们不建议使用同步方法,因为同步调用方法可能会产生严重的性能问题,并为你的原生模块引入线程相关的错误。此外,请注意,如果你选择使用 `RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD`,你的应用程序将无法再使用 Google Chrome 调试器。这是因为同步方法要求 JS VM 与应用程序共享内存。对于 Google Chrome 调试器,React Native 运行在 Google Chrome 中的 JS VM 内,并通过 WebSockets 与移动设备进行异步通信。
+
+### 测试你构建的内容
+
+此时,你已经在 iOS 中为原生模块设置了基本的脚手架。通过在 JavaScript 中访问原生模块并调用其导出的方法来测试它。
+
+在你的应用中找到一个位置来添加对原生模块 `createCalendarEvent()` 方法的调用。下面是一个你可以在应用中添加的组件 `NewModuleButton` 的示例。你可以在 `NewModuleButton` 的 `onPress()` 函数中调用原生模块。
+
+```tsx
+import React from 'react';
+import {Button} from 'react-native';
+
+const NewModuleButton = () => {
+ const onPress = () => {
+ console.log('We will invoke the native module here!');
+ };
+
+ return (
+
+ );
+};
+
+export default NewModuleButton;
+```
+
+为了从 JavaScript 访问你的原生模块,你需要先从 React Native 导入 `NativeModules`:
+
+```tsx
+import {NativeModules} from 'react-native';
+```
+
+然后你可以从 `NativeModules` 访问 `CalendarModule` 原生模块。
+
+```tsx
+const {CalendarModule} = NativeModules;
+```
+
+现在你已经可以访问 CalendarModule 原生模块了,你可以调用你的原生方法 `createCalendarEvent()`。以下是在 `NewModuleButton` 的 `onPress()` 方法中添加的代码:
+
+```tsx
+const onPress = () => {
+ CalendarModule.createCalendarEvent('testName', 'testLocation');
+};
+```
+
+最后一步是重新构建 React Native 应用,以便可以使用最新的原生代码(包含你的新原生模块!)。在 React Native 应用所在的命令行中,运行以下命令:
+
+
+
+
+```shell
+npm run ios
+```
+
+
+
+
+```shell
+yarn ios
+```
+
+
+
+
+### 迭代构建
+
+当你使用这些指南并迭代你的原生模块时,你需要进行原生重新构建应用程序,以便从 JavaScript 访问你最近的更改。这是因为你编写的代码位于应用程序的原生部分。虽然 React Native 的 metro 打包器可以监视 JavaScript 中的更改并即时重新构建 JS 包,但它不会对原生代码这样做。因此,如果你想测试最新的原生更改,你需要使用上述命令重新构建。
+
+### 回顾✨
+
+现在你应该能够在 JavaScript 中调用你的原生模块上的 `createCalendarEvent()` 方法。由于你在函数中使用了 `RCTLog`,你可以通过[在应用中启用调试模式](https://reactnative.dev/docs/debugging#chrome-developer-tools)并在 Chrome 或移动应用调试器 Flipper 中查看 JS 控制台来确认你的原生方法正在被调用。每次调用原生模块方法时,你都应该看到 `RCTLogInfo(@"Pretending to create an event %@ at %@", name, location);` 消息。
+
+
+
+ Flipper 中的 iOS 日志
+
+
+此时你已经创建了一个 iOS 原生模块并从 React Native 应用中的 JavaScript 调用了它的方法。你可以继续阅读以了解更多内容,比如你的原生模块方法接受哪些参数类型,以及如何在原生模块中设置回调和 Promise。
+
+## 超越日历原生模块
+
+### 更好的原生模块导出方式
+
+像上面那样从 `NativeModules` 中提取你的原生模块导入方式有点笨拙。
+
+为了让你的原生模块的使用者不必每次都这样做,你可以为该模块创建一个 JavaScript 包装器。创建一个名为 NativeCalendarModule.js 的新 JavaScript 文件,内容如下:
+
+```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;
+export default CalendarModule;
+```
+
+这个 JavaScript 文件也是添加任何 JavaScript 端功能的好地方。例如,如果你使用像 TypeScript 这样的类型系统,你可以在这里为你的原生模块添加类型注解。虽然 React Native 还不支持从原生到 JS 的类型安全,但有了这些类型注解,你所有的 JS 代码都将具有类型安全。这些注解也将使你将来更容易切换到类型安全的原生模块。以下是一个为日历模块添加类型安全的示例:
+
+```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;
+interface CalendarInterface {
+ createCalendarEvent(name: string, location: string): void;
+}
+export default CalendarModule as CalendarInterface;
+```
+
+在你的其他 JavaScript 文件中,你可以这样访问原生模块并调用它的方法:
+
+```tsx
+import NativeCalendarModule from './NativeCalendarModule';
+NativeCalendarModule.createCalendarEvent('foo', 'bar');
+```
+
+:::note
+这假设你导入 `CalendarModule` 的位置与 `NativeCalendarModule.js` 处于相同的目录层级。请根据需要更新相对导入路径。
+:::
+
+### 参数类型
+
+当在 JavaScript 中调用原生模块方法时,React Native 会将参数从 JS 对象转换为其 Objective-C/Swift 对象对应物。例如,如果你的 Objective-C 原生模块方法接受一个 NSNumber,在 JS 中你需要用一个数字来调用该方法。React Native 会为你处理转换。下面是原生模块方法支持的参数类型及其 JavaScript 等价物的列表。
+
+| Objective-C | JavaScript |
+| --------------------------------------------- | ------------------ |
+| NSString | string, ?string |
+| BOOL | boolean |
+| double | number |
+| NSNumber | ?number |
+| NSArray | Array, ?Array |
+| NSDictionary | Object, ?Object |
+| RCTResponseSenderBlock | Function (success) |
+| RCTResponseSenderBlock, RCTResponseErrorBlock | Function (failure) |
+| RCTPromiseResolveBlock, RCTPromiseRejectBlock | Promise |
+
+:::info
+以下类型目前受支持,但在 TurboModules 中将不再支持。请避免使用它们。
+
+- Function (failure) -> RCTResponseErrorBlock
+- Number -> NSInteger
+- Number -> CGFloat
+- Number -> float
+ :::
+
+对于 iOS,你还可以使用 `RCTConvert` 类支持的任何参数类型来编写原生模块方法(有关支持的类型的详细信息,请参阅 [RCTConvert](https://github.com/facebook/react-native/blob/main/packages/react-native/React/Base/RCTConvert.h))。RCTConvert 辅助函数都接受一个 JSON 值作为输入,并将其映射到原生 Objective-C 类型或类。
+
+### 导出常量
+
+原生模块可以通过重写原生方法 `constantsToExport()` 来导出常量。下面重写了 `constantsToExport()`,返回一个包含默认事件名称属性的字典,你可以在 JavaScript 中这样访问:
+
+```objectivec
+- (NSDictionary *)constantsToExport
+{
+ return @{ @"DEFAULT_EVENT_NAME": @"New Event" };
+}
+```
+
+然后可以通过在 JS 中调用原生模块的 `getConstants()` 来访问该常量:
+
+```tsx
+const {DEFAULT_EVENT_NAME} = CalendarModule.getConstants();
+console.log(DEFAULT_EVENT_NAME);
+```
+
+从技术上讲,可以直接从 `NativeModule` 对象访问在 `constantsToExport()` 中导出的常量。这在 TurboModules 中将不再受支持,因此我们鼓励社区切换到上述方法,以避免将来需要进行不必要的迁移。
+
+:::note
+常量仅在初始化时导出,因此如果你在运行时更改 `constantsToExport()` 的值,不会影响 JavaScript 环境。
+:::
+
+对于 iOS,如果你重写了 `constantsToExport()`,那么你还应该实现 `+ requiresMainQueueSetup`,以便让 React Native 知道你的模块是否需要在主线程上初始化,在任何 JavaScript 代码执行之前。否则你会看到一个警告,提示将来你的模块可能会在后台线程上初始化,除非你明确使用 `+ requiresMainQueueSetup:` 选择退出。如果你的模块不需要访问 UIKit,那么你应该对 `+ requiresMainQueueSetup` 返回 NO。
+
+### 回调
+
+原生模块还支持一种特殊的参数——回调。回调用于将数据从 Objective-C 传递给 JavaScript 的异步方法。它们也可以用于从原生端异步执行 JS。
+
+对于 iOS,回调使用 `RCTResponseSenderBlock` 类型实现。下面将回调参数 `myCallBack` 添加到 `createCalendarEventMethod()` 中:
+
+```objectivec
+RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title
+ location:(NSString *)location
+ myCallback:(RCTResponseSenderBlock)callback)
+
+```
+
+然后你可以在原生函数中调用回调,提供你想要传递给 JavaScript 的任何结果,放在一个数组中。请注意,`RCTResponseSenderBlock` 只接受一个参数——要传递给 JavaScript 回调的参数数组。下面你将传回在先前调用中创建的事件的 ID。
+
+:::info
+重要的是要强调,回调并不是在原生函数完成后立即调用的——请记住通信是异步的。
+:::
+
+```objectivec
+RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title location:(NSString *)location callback: (RCTResponseSenderBlock)callback)
+{
+ NSInteger eventId = ...
+ callback(@[@(eventId)]);
+
+ RCTLogInfo(@"Pretending to create an event %@ at %@", title, location);
+}
+
+```
+
+然后可以使用以下方式在 JavaScript 中访问此方法:
+
+```tsx
+const onSubmit = () => {
+ CalendarModule.createCalendarEvent(
+ 'Party',
+ '04-12-2020',
+ eventId => {
+ console.log(`Created a new event with id ${eventId}`);
+ },
+ );
+};
+```
+
+原生模块应该只调用其回调一次。但是,它可以保存 callback 并在以后调用。此模式通常用于封装需要委托的 iOS API——请参阅 [`RCTAlertManager`](https://github.com/facebook/react-native/blob/main/packages/react-native/React/CoreModules/RCTAlertManager.mm) 作为示例。如果回调从未被调用,则会泄漏一些内存。
+
+有两种处理回调错误的方法。第一种是遵循 Node 的约定,将传递给回调数组的第一个参数视为错误对象。
+
+```objectivec
+RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title location:(NSString *)location callback: (RCTResponseSenderBlock)callback)
+{
+ NSNumber *eventId = [NSNumber numberWithInt:123];
+ callback(@[[NSNull null], eventId]);
+}
+```
+
+在 JavaScript 中,你可以检查第一个参数以查看是否传递了错误:
+
+```tsx
+const onPress = () => {
+ CalendarModule.createCalendarEventCallback(
+ 'testName',
+ 'testLocation',
+ (error, eventId) => {
+ if (error) {
+ console.error(`Error found! ${error}`);
+ }
+ console.log(`event id ${eventId} returned`);
+ },
+ );
+};
+```
+
+另一个选择是使用两个单独的回调:onFailure 和 onSuccess。
+
+```objectivec
+RCT_EXPORT_METHOD(createCalendarEventCallback:(NSString *)title
+ location:(NSString *)location
+ errorCallback: (RCTResponseSenderBlock)errorCallback
+ successCallback: (RCTResponseSenderBlock)successCallback)
+{
+ @try {
+ NSNumber *eventId = [NSNumber numberWithInt:123];
+ successCallback(@[eventId]);
+ }
+
+ @catch ( NSException *e ) {
+ errorCallback(@[e]);
+ }
+}
+```
+
+然后在 JavaScript 中,你可以为错误和成功响应分别添加回调:
+
+```tsx
+const onPress = () => {
+ CalendarModule.createCalendarEventCallback(
+ 'testName',
+ 'testLocation',
+ error => {
+ console.error(`Error found! ${error}`);
+ },
+ eventId => {
+ console.log(`event id ${eventId} returned`);
+ },
+ );
+};
+```
+
+如果你想向 JavaScript 传递类似错误的对象,请使用 [`RCTUtils.h`](https://github.com/facebook/react-native/blob/main/packages/react-native/React/Base/RCTUtils.h) 中的 `RCTMakeError`。目前它只是向 JavaScript 传递一个 Error 形状的字典,但 React Native 的目标是在将来自动生成真正的 JavaScript Error 对象。你还可以提供一个 `RCTResponseErrorBlock` 参数,用于错误回调并接受一个 `NSError \* object`。请注意,此参数类型在 TurboModules 中将不被支持。
+
+### Promises
+
+原生模块还可以实现 Promise,这可以简化你的 JavaScript 代码,尤其是在使用 ES2016 的 `async/await` 语法时。当原生模块方法的最后一个参数是 `RCTPromiseResolveBlock` 和 `RCTPromiseRejectBlock` 时,其对应的 JS 方法将返回一个 JS Promise 对象。
+
+将上面的代码重构为使用 Promise 而不是回调,如下所示:
+
+```objectivec
+RCT_EXPORT_METHOD(createCalendarEvent:(NSString *)title
+ location:(NSString *)location
+ resolver:(RCTPromiseResolveBlock)resolve
+ rejecter:(RCTPromiseRejectBlock)reject)
+{
+ NSInteger eventId = createCalendarEvent();
+ if (eventId) {
+ resolve(@(eventId));
+ } else {
+ reject(@"event_failure", @"no event id returned", nil);
+ }
+}
+
+```
+
+此方法的 JavaScript 对应方法返回一个 Promise。这意味着你可以在 async 函数中使用 `await` 关键字来调用它并等待结果:
+
+```tsx
+const onSubmit = async () => {
+ try {
+ const eventId = await CalendarModule.createCalendarEvent(
+ 'Party',
+ 'my house',
+ );
+ console.log(`Created a new event with id ${eventId}`);
+ } catch (e) {
+ console.error(e);
+ }
+};
+```
+
+### 向 JavaScript 发送事件
+
+即使没有被 JavaScript 直接调用,原生模块也可以向 JavaScript 发送事件信号。例如,你可能想向 JavaScript 发送一个提醒,表示来自原生 iOS 日历应用的日历事件即将发生。最好的方法是子类化 `RCTEventEmitter`,实现 `supportedEvents` 并调用 `self sendEventWithName`:
+
+更新你的头文件类以导入 `RCTEventEmitter` 并子类化 `RCTEventEmitter`:
+
+```objectivec
+// CalendarModule.h
+
+#import
+#import
+
+@interface CalendarModule : RCTEventEmitter
+@end
+
+```
+
+JavaScript 代码可以通过在你的模块周围创建一个新的 `NativeEventEmitter` 实例来订阅这些事件。
+
+如果你在没有监听器的情况下触发事件,将会收到一个资源浪费的警告。为了避免这种情况,并优化你的模块工作负载(例如取消订阅上游通知或暂停后台任务),你可以在 `RCTEventEmitter` 子类中覆盖 `startObserving` 和 `stopObserving`。
+
+```objectivec
+@implementation CalendarModule
+{
+ bool hasListeners;
+}
+
+// Will be called when this module's first listener is added.
+-(void)startObserving {
+ hasListeners = YES;
+ // Set up any upstream listeners or background tasks as necessary
+}
+
+// Will be called when this module's last listener is removed, or on dealloc.
+-(void)stopObserving {
+ hasListeners = NO;
+ // Remove upstream listeners, stop unnecessary background tasks
+}
+
+- (void)calendarEventReminderReceived:(NSNotification *)notification
+{
+ NSString *eventName = notification.userInfo[@"name"];
+ if (hasListeners) {// Only send events if anyone is listening
+ [self sendEventWithName:@"EventReminder" body:@{@"name": eventName}];
+ }
+}
+
+```
+
+### 线程
+
+除非原生模块提供自己的方法队列,否则它不应该对自己被调用时所处的线程做任何假设。目前,如果原生模块不提供方法队列,React Native 将为其创建一个单独的 GCD 队列并在其中调用其方法。请注意,这是一个实现细节,将来可能会改变。如果你想明确为原生模块提供方法队列,请在原生模块中重写 `(dispatch_queue_t) methodQueue` 方法。例如,如果它需要使用仅限主线程的 iOS API,应该通过以下方式指定:
+
+```objectivec
+- (dispatch_queue_t)methodQueue
+{
+ return dispatch_get_main_queue();
+}
+```
+
+类似地,如果一个操作可能需要很长时间才能完成,原生模块可以指定自己的队列来运行操作。再次强调,目前 React Native 会为你的原生模块提供一个单独的方法队列,但这是一个你不应该依赖的实现细节。如果你不提供自己的方法队列,将来你的原生模块的长时间运行操作可能会阻塞在其他不相关的原生模块上执行的异步调用。`RCTAsyncLocalStorage` 模块在这里创建了自己的队列,这样 React 队列就不会因为可能较慢的磁盘访问而被阻塞。
+
+```objectivec
+- (dispatch_queue_t)methodQueue
+{
+ return dispatch_queue_create("com.facebook.React.AsyncLocalStorageQueue", DISPATCH_QUEUE_SERIAL);
+}
+```
+
+指定的 `methodQueue` 将由你模块中的所有方法共享。如果你的方法中只有一个方法是长时间运行的(或者由于某种原因需要在不同的队列中运行),你可以在方法体内使用 `dispatch_async` 在另一个队列中执行该特定方法的代码,而不会影响其他方法:
+
+```objectivec
+RCT_EXPORT_METHOD(doSomethingExpensive:(NSString *)param callback:(RCTResponseSenderBlock)callback)
+{
+ dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
+ // 在后台线程上执行长时间运行的代码
+ ...
+ // 你可以从任何线程/队列调用回调
+ callback(@[...]);
+ });
+}
+
+```
+
+:::info 在模块之间共享调度队列
+`methodQueue` 方法会在模块初始化时调用一次,然后由 React Native 保留,因此你自己不需要保留对该队列的引用,除非你希望在模块中使用它。但是,如果你希望在多个模块之间共享同一个队列,那么你需要确保为每个模块保留并返回相同的队列实例。
+:::
+
+### 依赖注入
+
+React Native 会自动创建和初始化任何注册的原生模块。但是,你可能希望创建和初始化自己的模块实例,例如注入依赖项。
+
+你可以通过创建一个实现 `RCTBridgeDelegate` 协议的类来实现这一点,用该委托初始化一个 `RCTBridge`,并用初始化的桥接器初始化一个 `RCTRootView`。
+
+```objectivec
+id moduleInitialiser = [[classThatImplementsRCTBridgeDelegate alloc] init];
+
+RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:moduleInitialiser launchOptions:nil];
+
+RCTRootView *rootView = [[RCTRootView alloc]
+ initWithBridge:bridge
+ moduleName:kModuleName
+ initialProperties:nil];
+```
+
+### 导出 Swift 模块
+
+Swift 不支持宏,因此在 React Native 中向 JavaScript 暴露原生模块及其方法需要更多的设置。不过,它的工作方式基本相同。假设你有一个相同的 `CalendarModule`,但它是用 Swift 实现的类:
+
+```swift
+// CalendarModule.swift
+
+@objc(CalendarModule)
+class CalendarModule: NSObject {
+
+ @objc(addEvent:location:date:)
+ func addEvent(_ name: String, location: String, date: NSNumber) -> Void {
+ // Date is ready to use!
+ }
+
+ @objc
+ func constantsToExport() -> [String: Any]! {
+ return ["someKey": "someValue"]
+ }
+
+}
+```
+
+:::note
+使用 `@objc` 修饰符以确保类和函数正确导出到 Objective-C 运行时非常重要。
+:::
+
+然后创建一个私有实现文件,将所需信息注册到 React Native:
+
+```objectivec
+// CalendarModuleBridge.m
+#import
+
+@interface RCT_EXTERN_MODULE(CalendarModule, NSObject)
+
+RCT_EXTERN_METHOD(addEvent:(NSString *)name location:(NSString *)location date:(nonnull NSNumber *)date)
+
+@end
+```
+
+如果你不熟悉 Swift 和 Objective-C,当你[在 iOS 项目中混合使用两种语言](https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html)时,你还需要一个额外的桥接头文件,称为 bridging header,用于将 Objective-C 文件暴露给 Swift。如果你通过 Xcode 菜单中的 `File>New File` 添加 Swift 文件,Xcode 会自动为你创建这个头文件。你需要在这个头文件中导入 `RCTBridgeModule.h`。
+
+```objectivec
+// CalendarModule-Bridging-Header.h
+#import
+```
+
+你还可以使用 `RCT_EXTERN_REMAP_MODULE` 和 `_RCT_EXTERN_REMAP_METHOD` 来更改你正在导出的模块或方法的 JavaScript 名称。更多信息请参阅 [`RCTBridgeModule`](https://github.com/facebook/react-native/blob/main/packages/react-native/React/Base/RCTBridgeModule.h)。
+
+:::note
+制作第三方模块时的重要注意事项:只有 Xcode 9 及更高版本才支持在静态库中使用 Swift。为了在使用模块中包含的 iOS 静态库中的 Swift 时构建 Xcode 项目,你的主应用项目必须包含 Swift 代码和桥接头文件本身。如果你的应用项目不包含任何 Swift 代码,一个解决方法是添加一个空的 .swift 文件和一个空的桥接头文件。
+:::
+
+### 保留方法名
+
+#### invalidate()
+
+在 iOS 上,原生模块可以通过实现 `invalidate()` 方法来符合 [RCTInvalidating](https://github.com/facebook/react-native/blob/main/packages/react-native/React/Base/RCTInvalidating.h) 协议。当原生桥接失效时(例如在开发模式重新加载时),可以[调用](https://github.com/facebook/react-native/blob/0.62-stable/ReactCommon/turbomodule/core/platform/ios/RCTTurboModuleManager.mm#L456)此方法。请根据需要使用此机制为你的原生模块执行必要的清理工作。
diff --git a/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-setup.md b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-setup.md
new file mode 100644
index 00000000000..8bccdea97b9
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/legacy/native-modules-setup.md
@@ -0,0 +1,35 @@
+---
+id: native-modules-setup
+title: 原生模块配置
+---
+
+import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecation.mdx'
+
+
+
+原生模块通常作为 npm 包分发,除了常规的 JavaScript 外,它们还会包含每个平台的一些本地代码。要了解更多关于 npm 包的信息,你可能会发现[这个指南](https://docs.npmjs.com/packages-and-modules/contributing-packages-to-the-registry)很有用。
+
+为了设置一个原生模块的基本项目结构,我们将使用社区工具[Bob](https://github.com/react-native-community/bob)。你可以继续深入了解该库的工作原理,但对于我们的需求,我们只需要执行基本的`create`脚本:
+
+```sh
+npx @react-native-community/bob create react-native-awesome-module
+```
+
+`react-native-awesome-module` 是您希望为新模块命名的名称。完成此操作后,在终端进入到 `react-native-awesome-module` 文件夹,并运行以下命令来引导示例项目:
+
+```sh
+yarn bootstrap
+```
+
+当引导完成后,您可以通过执行以下任一命令启动示例应用程序:
+
+```sh
+# Android app
+yarn example android
+# iOS app
+yarn example ios
+```
+
+当完成上述所有步骤后,您将能够继续使用 [Android Native Modules](native-modules-android) 或 [iOS Native Modules](native-modules-ios) 指南来添加一些代码。
+
+> 想要一个不那么主观的设置?可查看第三方工具 [create-react-native-module](https://github.com/brodybits/create-react-native-module)。
diff --git a/cnwebsite/versioned_docs/version-0.85/libraries.md b/cnwebsite/versioned_docs/version-0.85/libraries.md
new file mode 100644
index 00000000000..43647d3a687
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/libraries.md
@@ -0,0 +1,120 @@
+---
+id: libraries
+title: 使用第三方库
+author: Brent Vatne
+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';
+
+React Native 提供了一系列内置的[核心组件和 API](./components-and-apis),但并不局限于此。React Native 有一个由数千名开发者组成的庞大社区。如果核心组件和 API 不能满足你的需求,你完全可以去社区中寻求合适的第三方库来为你的应用添加功能。
+
+## 选择一个包管理器
+
+通常,React Native 库是从 [npm 源](https://www.npmjs.com/) 安装的,使用诸如 [npm CLI](https://docs.npmjs.com/cli/npm) 或 [Yarn 经典版](https://classic.yarnpkg.com/en/) 的 Node.js 包管理器。
+
+如果你的电脑上安装了 Node.js,那么你已经有了 npm CLI。一些开发者更喜欢使用 Yarn 经典版,因为它具有略快的安装时间和额外的高级功能,如 Workspaces。这两种工具都可以很好地支持 React Native。为了简化说明,在本指南的其余部分我们将假设使用 npm。
+
+:::note
+在 JavaScript 社区中,"库(library)"和"包(package)"这两个术语一直是混用的,可视为等同。
+:::
+
+## 安装第三方库
+
+要在你的项目中安装一个库,你需要在终端里进入你的项目目录然后运行安装命令。我们来用 `react-native-webview` 试试:
+
+
+
+
+```shell
+npm install react-native-webview
+```
+
+
+
+
+```shell
+yarn add react-native-webview
+```
+
+
+
+
+我们刚刚安装的这个库包含了原生代码,我们需要在应用中链接它才能使用。
+
+## 链接 iOS 原生代码
+
+React Native 使用 CocoaPods 来管理 iOS 项目的依赖项,大多数 React Native 库都遵循这个约定。如果你使用的库不是这样的,请参考它们的 README 获取额外的指导。在大多数情况下以下说明都适用。
+
+在 `ios` 目录下运行 `pod install` 将其链接到原生 iOS 项目。一个不需要切换到 `ios` 目录就可以做到这一点的快捷方式是运行 `npx pod-install`。
+
+```bash
+npx pod-install
+```
+
+完成后,重新构建应用程序以开始使用新库:
+
+
+
+
+```shell
+npm run ios
+```
+
+
+
+
+```shell
+yarn ios
+```
+
+
+
+
+## 链接 Android 原生代码
+
+React Native 使用 Gradle 来管理 Android 项目的依赖关系。在安装了带有原生依赖项的库之后,你需要重新构建应用程序以使用新库:
+
+
+
+
+```shell
+npm run android
+```
+
+
+
+
+```shell
+yarn android
+```
+
+
+
+
+## 搜索第三方库
+
+[React Native 目录](https://reactnative.directory)是一个可搜索的数据库,收录了专门为 React Native 构建的库。这是寻找适用于你的 React Native 应用的库的第一站。
+
+你在目录中找到的许多库来自 [React Native 社区](https://github.com/react-native-community/) 或者 [Expo](https://docs.expo.dev/versions/latest/)。
+
+由 React Native 社区构建的库是由志愿者和依赖 React Native 的公司的个人推动的。它们通常支持 iOS、tvOS、Android、Windows,但这在各个项目之间有所不同。这个组织中的许多库曾经是 React Native 的核心组件和 API。
+
+由 Expo 构建的库都用 TypeScript 编写,并尽可能支持 iOS、Android 和 `react-native-web`。
+
+如果在 React Native 目录找不到专门针对 React Native 的库,[npm 源](https://www.npmjs.com/) 是下一个最佳选择。npm 源是 JavaScript 库的权威来源,但它列出的库可能并非都与 React Native 兼容。React Native 是众多 JavaScript 运行环境之一,类似 Node.js、Web 浏览器、Electron 等,而 npm 中存放了适用于所有这些环境的库。
+
+## 判断第三方库的兼容性
+
+### 它支持 React Native 吗?
+
+通常为其他平台特别构建的库与 React Native 不兼容。例如,`react-select`是为 Web 构建的,专门针对`react-dom`,而`rimraf`是为 Node.js 构建的,并与计算机文件系统交互。像`lodash`这样的库仅使用 JavaScript 语言特性,在任何环境中都可以工作。随着时间的推移你将对此有所了解,但在那之前,最简单的方法是自己尝试。如果发现它在 React Native 中不起作用,你可以使用`npm uninstall`来移除包。
+
+### 它支持某个系统平台吗?
+
+[React Native 目录](https://reactnative.directory)允许你根据平台兼容性进行筛选,例如 iOS、Android、Web 和 Windows。如果你想要使用的库目前在其中没有列出,请参考库的 README 了解更多信息。
+
+### 它支持我的 React Native 版本吗?
+
+一个库的最新版本通常与最新版本的 React Native 兼容。如果你使用的是旧版本,你应当查阅 README 文件了解应该安装该库的哪个版本。你可以通过运行 `npm install @` 命令来安装特定版本的库,例如:`npm install @react-native-community/netinfo@^2.0.0`。
diff --git a/cnwebsite/versioned_docs/version-0.85/linking-libraries-ios.md b/cnwebsite/versioned_docs/version-0.85/linking-libraries-ios.md
new file mode 100644
index 00000000000..96317966679
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/linking-libraries-ios.md
@@ -0,0 +1,59 @@
+---
+id: linking-libraries-ios
+title: 链接原生库
+---
+
+并不是所有的 APP 都需要使用全部的原生功能,包含支持全部特性的代码会增大应用的体积。但我们仍然希望能让你简单地根据自己的需求添加需要的特性。
+
+在这种思想下,我们把许多特性都发布成为互不相关的静态库。
+
+大部分的库只需要拖进两个文件就可以使用了,偶尔你还需要几步额外的工作,但不会再有更多的事情要做了。
+
+_我们随着 React Native 发布的所有库都在仓库中的`Libraries`文件夹下。其中有一些是纯 Javascript 代码,你只需要去`import`它们就可以使用了。另外有一些库基于一些原生代码实现,你必须把这些文件添加到你的应用,否则应用会在你使用这些库的时候产生报错。_
+
+## 添加包含原生代码的库需要几个步骤:
+
+### 自动链接
+
+安装某个带原生依赖的库:
+
+```bash
+$ npm install 某个带有原生依赖的库
+$ npx pod-install
+```
+
+:::info 提示
+React Native 只会读取`package.json`中列出的`dependencies` 和 `devDependencies`来进行自动链接。
+:::
+
+这样就可以了!由于集成了 [autolinking](https://github.com/react-native-community/cli/blob/main/docs/autolinking.md) 机制,下次你构建你的应用时原生代码就会自动链接了。
+
+### 手动链接
+
+#### 第一步
+
+如果该库包含原生代码,那么在它的文件夹下一定有一个`.xcodeproj`文件。把这个文件拖到你的 XCode 工程下(通常拖到 XCode 的`Libraries`分组里)
+
+
+
+#### 第二步
+
+点击你的主工程文件,选择`Build Phases`,然后把刚才所添加进去的`.xcodeproj`下的`Products`文件夹中的静态库文件(.a 文件),拖到`Link Binary With Libraries`组内。
+
+
+
+#### 第三步
+
+不是所有的库都需要进行这个步骤,你需要考虑的问题在于:
+
+_我需要在编译的期间了解库的内容吗?_
+
+这个问题的意思是,你是需要在原生代码中使用这个库,还是只需要通过 JavaScript 访问?如果你只需要通过 JavaScript 访问这个库,你就可以跳过这步了。
+
+这一步骤对于我们随 React Native 发布的大部分库来说都不是必要的,但有两个例外是`PushNotificationIOS`和`LinkingIOS`。
+
+以`PushNotificationIOS`为例,你需要在`AppDelegate`每收到一条推送通知之后,调用库中的一个方法。
+
+这种情况下我们需要能够访问到库的头文件。为了能够顺利打包,你需要打开你的工程文件,选择`Build Settings`,然后搜索`Header Search Paths`,然后添加库所在的目录。
+
+
diff --git a/cnwebsite/versioned_docs/version-0.85/linking.md b/cnwebsite/versioned_docs/version-0.85/linking.md
new file mode 100644
index 00000000000..601f83c8294
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/linking.md
@@ -0,0 +1,691 @@
+---
+id: linking
+title: Linking
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+`Linking`提供了一个通用的接口来与传入和传出的 App 链接进行交互。
+
+每个链接(URL)都有一个 URL Scheme,有些网站以 `https://` 或 `http://` 为前缀,而 `http` 就是 URL Scheme。我们简称它为 scheme。
+
+除了 `https`,你可能还熟悉 `mailto` scheme。当您打开带有 mailto scheme 的链接时,操作系统将打开已安装的邮件应用程序。同样,也有打电话和发短信的 schemes。阅读下面关于[内置 URL schemes](#built-in-url-schemes) 方案的更多信息。
+
+与使用 mailto scheme 一样,可以通过使用自定义 url scheme 链接到其他应用程序。例如,当你收到一封来自 Slack 的 **Magic Link** 邮件时,**Launch Slack** 按钮是一个 anchor 标记,带有一个 href,看起来类似与 `slack://secret/magic-login/other-secret`。就像 Slack 一样,你可以告诉操作系统你想要处理一个自定义 scheme。当 Slack 应用程序打开时,它会接收用于打开它的 URL。这通常被称为 Deep Links。阅读更多关于如何[获得 Deep Links](#get-the-deep-link) 到你的应用程序。
+
+自定义 URL scheme 并不是在手机上打开应用程序的唯一方式。您不希望在电子邮件中的链接中使用自定义 URL scheme,因为这样链接在桌面上就会断开。相反,你想使用常规的 `https` 链接,如 `https://www.myapp.io/records/1234546`。在移动设备上,你希望这个链接打开你的应用程序。Android 称之为 **Deep Links** (Universal Links - iOS)。
+
+### 内置 URL Schemes
+
+正如在介绍中提到的,每个平台上都存在一些核心功能的 URL schemes。以下是一个非详尽的列表,但涵盖了最常用的方案。
+
+| Scheme | 说明 | iOS | Android |
+| ---------------- | -------------------------------------------- | --- | ------- |
+| `mailto` | 打开 mail app, 例如: mailto: support@expo.io | ✅ | ✅ |
+| `tel` | 打开 phone app, 例如: tel:+123456789 | ✅ | ✅ |
+| `sms` | 打开 SMS app, 例如: sms:+123456789 | ✅ | ✅ |
+| `https` / `http` | 打开 web browser app, 例如: https://expo.io | ✅ | ✅ |
+
+### 基本用法
+
+### 启用 Deep Links
+
+
+
仅适用于非沙盒项目
+
+ 以下部分仅适用于 Native 项目。如果您正在使用 Expo 工作流,请参阅 Expo 文档中 Linking 的指南,以获取正确替代方案。
+
+
+
+如果你想在你的应用程序中启用 Deep Links,请遵循以下指南:
+
+
+
+
+:::info
+要了解更多如何在 Android 上支持深度链接的说明,请参阅[Enabling Deep Links for App Content - Add Intent Filters for Your Deep Links](https://developer.android.com/training/app-indexing/deep-linking.html#adding-filters)。
+:::
+
+如果要在现有的 MainActivity 中监听传入的 intent,那么需要在`AndroidManifest.xml`中将 MainActivity 的`launchMode`设置为`singleTask`。相关解释可参考[``](https://developer.android.com/guide/topics/manifest/activity-element.html)文档。
+
+```xml
+
+```
+
+
+
+
+:::note
+对于 iOS 来说,如果要在 App 启动后也监听传入的 App 链接,那么首先需要按照[步骤 3](linking-libraries-ios#step-3)中的说明将`LinkingIOS`文件夹添加到头文件搜索路径中。如果还想在 App 运行期间监听传入的 App 链接,那么需要在`*AppDelegate.m`中增加以下代码:
+
+
+
+
+```objc title="AppDelegate.mm"
+// iOS 9.x 或更高版本
+#import
+
+- (BOOL)application:(UIApplication *)application
+ openURL:(NSURL *)url
+ options:(NSDictionary *)options
+{
+ return [RCTLinkingManager application:application openURL:url options:options];
+}
+```
+
+如果你的 app 用了 [Universal Links](https://developer.apple.com/ios/universal-links/),需要正确的把下述代码添加进去:
+
+```objc title="AppDelegate.mm"
+- (BOOL)application:(UIApplication *)application continueUserActivity:(nonnull NSUserActivity *)userActivity
+ restorationHandler:(nonnull void (^)(NSArray> * _Nullable))restorationHandler
+{
+ return [RCTLinkingManager application:application
+ continueUserActivity:userActivity
+ restorationHandler:restorationHandler];
+}
+```
+
+
+
+
+```swift title="AppDelegate.swift"
+override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
+ return RCTLinkingManager.application(app, open: url, options: options)
+}
+```
+
+如果你的 app 用了 [Universal Links](https://developer.apple.com/ios/universal-links/),需要正确的把下述代码添加进去:
+
+```swift title="AppDelegate.swift"
+override func application(
+ _ application: UIApplication,
+ continue userActivity: NSUserActivity,
+ restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
+ return RCTLinkingManager.application(
+ application,
+ continue: userActivity,
+ restorationHandler: restorationHandler
+ )
+ }
+```
+
+
+
+
+:::
+
+### 处理 Deep Links
+
+有两种方法来处理打开应用程序的 URL。
+
+#### 1. 如果应用程序已经打开,应用程序就会出现在前台,并触发一个链接 'url' 事件
+
+你可以用 `Linking.addEventListener('url', callback)` 来处理这些事件——它使用链接的 URL 调用 `callback({ url })`
+
+#### 2. 如果应用程序还没有打开,它就会被打开,并将 url 作为 initialURL 传入
+
+你可以用 `Linking.getInitialURL()` 来处理这些事件——它会返回一个解析到 URL 的 Promise (如果有的话)。
+
+---
+
+## 示例
+
+### Open Links and Deep Links (Universal Links)
+
+
+
+
+```SnackPlayer name=Linking%20Example&supportedPlatforms=ios,android&ext=js
+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';
+
+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%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);
+
+ 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;
+```
+
+
+
+
+### Open Custom Settings
+
+
+
+
+```SnackPlayer name=Linking%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%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}: OpenSettingsButtonProps) => {
+ 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;
+```
+
+
+
+
+### 获取 Deep Link
+
+
+
+
+```SnackPlayer name=Linking%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);
+
+ 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%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();
+
+ // 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;
+```
+
+
+
+
+### 发送 Intents (Android)
+
+
+
+
+```SnackPlayer name=Linking%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 handlePress = useCallback(async () => {
+ try {
+ await Linking.sendIntent(action, extras);
+ } catch (e) {
+ Alert.alert(e.message);
+ }
+ }, [action, extras]);
+
+ return ;
+};
+
+const App = () => {
+ return (
+
+
+ Power Usage Summary
+
+
+ App Notification Settings
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Linking%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
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+});
+
+export default App;
+```
+
+
+
+
+# 文档
+
+## 方法
+
+### `addEventListener()`
+
+```tsx
+static addEventListener(
+ type: 'url',
+ handler: (event: {url: string}) => void,
+): EmitterSubscription;
+```
+
+通过监听 `url` 事件类型并提供处理程序,为链接更改添加处理程序。
+
+---
+
+### `canOpenURL()`
+
+```tsx
+static canOpenURL(url: string): Promise;
+```
+
+判断设备上是否有已经安装的应用可以处理指定的 URL。
+
+本方法会返回一个`Promise`对象。当确定传入的 URL 可以被处理时,promise 就会返回,值的第一个参数是表示是否可以打开 URL。
+
+如果无法检查 URL 是否可以打开,或者当目标为 Android 11 (SDK 30) 平台且您没有在 `AndroidManifest.xml` 中指定相关的 intent queries,则 `Promise` 将在 Android 上拒绝。类似地,在 iOS 上,如果你没有在 `Info.plist` 中的 `LSApplicationQueriesSchemes` 键中添加特定的 scheme,`Promise` 将被拒绝(见下文)。
+
+**参数:**
+
+| 名称 | 类型 | 说明 |
+| -------------------------------------------------------- | ------ | -------------- |
+| url Required
| string | 要打开的 URL。 |
+
+:::note
+对于 web 链接来说,协议头(`"http://"`, `"https://"`)不能省略!
+:::
+
+:::warning
+此方法在 iOS 9+ 上有限制。根据[Apple 官方文档](https://developer.apple.com/documentation/uikit/uiapplication/1622952-canopenurl):
+
+- 如果你的 app 链接了早期版本的 iOS 但运行在 iOS 9.0 或更高版本上,你可以调用此方法最多 50 次。达到该限制后,后续调用将始终解析为`false`。如果用户重新安装或升级 app,iOS 会重置该限制。
+- 从 iOS 9 开始,你的 app 还需要在`Info.plist`中提供`LSApplicationQueriesSchemes`键,否则`canOpenURL()`将始终解析为`false`。
+ :::
+
+:::info
+当目标为 Android 11 (SDK 30) 时,你必须在`AndroidManifest.xml`中指定要处理的 scheme 的 intent。可以在[这里](https://developer.android.com/guide/components/intents-common)找到常见 intent 的列表。
+
+例如,要处理`https` scheme,需要在 manifest 中添加以下内容:
+
+```
+
+
+
+
+
+
+
+
+```
+
+:::
+
+---
+
+### `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`.
+
+:::info
+要支持 Android 上的深度链接,请参考 https://developer.android.com/training/app-indexing/deep-linking.html#handling-intents。
+:::
+
+:::tip
+`getInitialURL` 在远程 JS 调试时可能返回`null`。请关闭调试器以确保能正常获取。
+:::
+
+---
+
+### `openSettings()`
+
+```tsx
+static openSettings(): Promise;
+```
+
+Open the Settings app and displays the app’s custom settings, if it has any.
+
+---
+
+### `openURL()`
+
+```tsx
+static openURL(url: string): Promise;
+```
+
+Try to open the given `url` with any of the installed apps.
+
+You can use other URLs, like a location (e.g. "geo:37.484847,-122.148386" on Android or "https://maps.apple.com/?ll=37.484847,-122.148386" on iOS), a contact, or any other URL that can be opened with the installed apps.
+
+The method returns a `Promise` object. If the user confirms the open dialog or the url automatically opens, the promise is resolved. If the user cancels the open dialog or there are no registered applications for the url, the promise is rejected.
+
+**参数:**
+
+| 名称 | 类型 | 说明 |
+| -------------------------------------------------------- | ------ | -------------- |
+| url Required
| string | 要打开的 URL。 |
+
+:::note
+如果系统不知道如何打开指定的 URL,此方法将失败。如果传入的是非 http(s) URL,最好先检查`canOpenURL()`。
+
+对于 web URL,协议(`"http://"`、`"https://"`)必须相应设置!
+:::
+
+:::warning
+此方法在模拟器中的行为可能不同,例如`"tel:"`链接在 iOS 模拟器中无法处理,因为没有拨号器 app。
+:::
+
+---
+
+### `sendIntent()` Android
+
+```tsx
+static sendIntent(
+ action: string,
+ extras?: Array<{key: string; value: string | number | boolean}>,
+): Promise;
+```
+
+启动 Android intent 时携带 extras。
+
+**参数:**
+
+| 名称 | 类型 |
+| ----------------------------------------------------------- | ---------------------------------------------------------- |
+| action Required
| string |
+| extras | `Array<{key: string, value: string | number | boolean}>` |
diff --git a/cnwebsite/versioned_docs/version-0.85/metro.md b/cnwebsite/versioned_docs/version-0.85/metro.md
new file mode 100644
index 00000000000..4578e9ab40a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/metro.md
@@ -0,0 +1,108 @@
+---
+id: metro
+title: Metro
+---
+
+React Native 使用[Metro](https://metrobundler.dev/)构建 JavaScript 代码和资源。
+
+## 配置 Metro
+
+可以在项目的`metro.config.js`文件中自定义 Metro 的配置选项。它可以导出:
+
+- **一个对象(推荐)**,将与 Metro 的内部配置默认值合并。
+- [**一个函数**](#advanced-using-a-config-function),该函数将使用 Metro 的内部配置默认值被调用,并返回最终的配置对象。
+
+:::tip
+请查看 Metro 网站上的[**配置 Metro**](https://metrobundler.dev/docs/configuration),了解所有可用的配置选项文档。
+:::
+
+在 React Native 中,你的 Metro 配置应该扩展[`@react-native/metro-config`](https://www.npmjs.com/package/@react-native/metro-config)或[`@expo/metro-config`](https://www.npmjs.com/package/@expo/metro-config)。这些包含构建和运行 React Native 应用所需的基本默认值。
+
+下面是 React Native 模板项目中默认的`metro.config.js`文件:
+
+```js
+const {
+ getDefaultConfig,
+ mergeConfig,
+} = require('@react-native/metro-config');
+
+/**
+ * Metro配置
+ * https://metrobundler.dev/docs/configuration
+ *
+ * @type {import('metro-config').MetroConfig}
+ */
+const config = {};
+
+module.exports = mergeConfig(getDefaultConfig(__dirname), config);
+```
+
+你希望自定义的 Metro 选项可以在`config`对象中完成。
+
+### 高级:使用配置函数
+
+导出一个配置函数是自行管理最终配置的选择 - **Metro 不会应用任何内部默认值**。当需要从 Metro 读取基础默认配置对象或动态设置选项时,此模式会很有用。
+
+:::info
+**从`@react-native/metro-config` 0.72.1 开始**,不再需要使用配置函数来访问完整的默认配置。请参阅下面的**提示**部分。
+:::
+
+```js
+const {
+ getDefaultConfig,
+ mergeConfig,
+} = require('@react-native/metro-config');
+
+module.exports = function (baseConfig) {
+ const defaultConfig = mergeConfig(
+ baseConfig,
+ getDefaultConfig(__dirname),
+ );
+ const {
+ resolver: {assetExts, sourceExts},
+ } = defaultConfig;
+
+ return mergeConfig(defaultConfig, {
+ resolver: {
+ assetExts: assetExts.filter(ext => ext !== 'svg'),
+ sourceExts: [...sourceExts, 'svg'],
+ },
+ });
+};
+```
+
+:::tip
+使用配置函数是为高级用例而设计的。如需自定义`sourceExts`等选项,一种更简单的方法是从`@react-native/metro-config`中读取这些默认值。
+
+**替代方案**
+
+```js
+const defaultConfig = getDefaultConfig(__dirname);
+
+const config = {
+ resolver: {
+ sourceExts: [...defaultConfig.resolver.sourceExts, 'svg'],
+ },
+};
+
+module.exports = mergeConfig(defaultConfig, config);
+```
+
+**但是!**,我们建议在覆盖这些配置值时复制并编辑 - 将真实来源放在你的配置文件中。
+
+✅ **推荐**
+
+```js
+const config = {
+ resolver: {
+ sourceExts: ['js', 'ts', 'tsx', 'svg'],
+ },
+};
+```
+
+:::
+
+## 了解更多关于 Metro 的信息
+
+- [Metro 网站](https://metrobundler.dev/)
+- [视频: "Metro & React Native DevX" 在 App.js 2023 上的演讲](https://www.youtube.com/watch?v=c9D4pg0y9cI)
diff --git a/cnwebsite/versioned_docs/version-0.85/modal.md b/cnwebsite/versioned_docs/version-0.85/modal.md
new file mode 100644
index 00000000000..95e3e50fa78
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/modal.md
@@ -0,0 +1,275 @@
+---
+id: modal
+title: Modal
+---
+
+Modal 组件是一种在外层视图之上展示内容的基本方式。
+
+## 示例
+
+```SnackPlayer name=Modal&supportedPlatforms=android,ios
+import React, {useState} from 'react';
+import {Alert, Modal, StyleSheet, Text, Pressable, View} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ const [modalVisible, setModalVisible] = useState(false);
+ return (
+
+
+ {
+ Alert.alert('Modal has been closed.');
+ setModalVisible(!modalVisible);
+ }}>
+
+
+ Hello World!
+ setModalVisible(!modalVisible)}>
+ Hide Modal
+
+
+
+
+ setModalVisible(true)}>
+ Show Modal
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ centeredView: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ modalView: {
+ margin: 20,
+ backgroundColor: 'white',
+ borderRadius: 20,
+ padding: 35,
+ alignItems: 'center',
+ shadowColor: '#000',
+ shadowOffset: {
+ width: 0,
+ height: 2,
+ },
+ shadowOpacity: 0.25,
+ shadowRadius: 4,
+ elevation: 5,
+ },
+ button: {
+ borderRadius: 20,
+ padding: 10,
+ elevation: 2,
+ },
+ buttonOpen: {
+ backgroundColor: '#F194FF',
+ },
+ buttonClose: {
+ backgroundColor: '#2196F3',
+ },
+ textStyle: {
+ color: 'white',
+ fontWeight: 'bold',
+ textAlign: 'center',
+ },
+ modalText: {
+ marginBottom: 15,
+ textAlign: 'center',
+ },
+});
+
+export default App;
+```
+
+---
+
+# 参考文档
+
+## Props
+
+### [View Props](view.md#props)
+
+继承 [View Props](view.md#props)。
+
+---
+
+### 🗑️ `animated`
+
+:::warning 已弃用
+请改用 [`animationType`](modal.md#animationtype) 属性。
+:::
+
+---
+
+### `animationType`
+
+`animationType` 属性控制模态框的动画方式。
+
+可选值:
+
+- `slide` 从底部滑入
+- `fade` 淡入显示
+- `none` 无动画直接出现
+
+| 类型 | 默认值 |
+| ----------------------------------- | ------ |
+| enum(`'none'`, `'slide'`, `'fade'`) | `none` |
+
+---
+
+### `backdropColor`
+
+模态框的背景色(即模态框容器的背景颜色)。如果未提供且 `transparent` 为 `false`,则默认为 `white`。当 `transparent` 为 `true` 时此属性被忽略。
+
+| 类型 | 默认值 |
+| --------------- | ------ |
+| [color](colors) | white |
+
+---
+
+### `hardwareAccelerated` Android
+
+`hardwareAccelerated` 属性控制是否为底层窗口强制启用硬件加速。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `navigationBarTranslucent` Android
+
+`navigationBarTranslucent` 属性决定模态框是否延伸到系统导航栏下方。但同时需要将 `statusBarTranslucent` 也设置为 `true` 才能使导航栏变为半透明。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `onDismiss` iOS
+
+`onDismiss` 属性允许传入一个函数,该函数会在模态框关闭后被调用。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onOrientationChange` iOS
+
+`onOrientationChange` 回调会在模态框显示期间设备方向发生变化时被调用。提供的方向值仅为 'portrait' 或 'landscape'。此回调在初次渲染时也会被调用,无论当前的设备方向如何。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `allowSwipeDismissal` iOS
+
+控制在 iOS 上是否可以通过下滑手势关闭模态框。使用此功能需要同时实现 `onRequestClose` 属性来处理关闭事件。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `ref`
+
+一个 ref 设置器,在组件挂载时会被赋值为一个[元素节点](element-nodes)。
+
+---
+
+### `onRequestClose`
+
+`onRequestClose` 回调会在用户按下 Android 上的硬件返回键或 Apple TV 上的菜单键时被调用。由于这是一个必需的属性,请注意只要模态框处于打开状态,`BackHandler` 事件就不会被触发。
+在 iOS 上,当使用 `pageSheet` 或 `formSheet` 的 `presentationStyle` 并通过拖拽手势关闭模态框时,也会调用此回调。当启用了 `allowSwipeDismissal` 时,此回调将在模态框关闭后被调用。
+
+| 类型 |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| function 必需
Android
TV
function iOS
|
+
+---
+
+### `onShow`
+
+`onShow` 属性允许传入一个函数,该函数会在模态框显示后被调用。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `presentationStyle` iOS
+
+`presentationStyle` 属性控制模态框的显示方式(通常用于较大设备,如 iPad 或大屏 iPhone)。详情请参阅 https://developer.apple.com/reference/uikit/uimodalpresentationstyle 。
+
+可选值:
+
+- `fullScreen` 覆盖整个屏幕
+- `pageSheet` 覆盖竖屏宽度的居中视图(仅限大屏设备)
+- `formSheet` 覆盖窄宽度的居中视图(仅限大屏设备)
+- `overFullScreen` 覆盖整个屏幕,但允许透明
+
+| 类型 | 默认值 |
+| ---------------------------------------------------------------------- | --------------------------------------------------------------------------------------- |
+| enum(`'fullScreen'`, `'pageSheet'`, `'formSheet'`, `'overFullScreen'`) | `transparent={false}` 时为 `fullScreen` `transparent={true}` 时为 `overFullScreen` |
+
+---
+
+### `statusBarTranslucent` Android
+
+`statusBarTranslucent` 属性决定模态框是否延伸到系统状态栏下方。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `supportedOrientations` iOS
+
+`supportedOrientations` 属性允许模态框旋转到指定的任何方向。在 iOS 上,模态框仍受应用 Info.plist 中 UISupportedInterfaceOrientations 字段所指定方向的限制。
+
+:::note
+当 `presentationStyle` 设置为 `pageSheet` 或 `formSheet` 时,此属性在 iOS 上会被忽略。
+:::
+
+| 类型 | 默认值 |
+| -------------------------------------------------------------------------------------------------------------- | -------------- |
+| array of enums(`'portrait'`, `'portrait-upside-down'`, `'landscape'`, `'landscape-left'`, `'landscape-right'`) | `['portrait']` |
+
+---
+
+### `transparent`
+
+`transparent` 属性决定模态框是否填充整个视图。将其设置为 `true` 会使模态框在透明背景上渲染。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `visible`
+
+`visible` 属性决定模态框是否可见。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
diff --git a/cnwebsite/versioned_docs/version-0.85/more-resources.md b/cnwebsite/versioned_docs/version-0.85/more-resources.md
new file mode 100644
index 00000000000..b72f4286a4a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/more-resources.md
@@ -0,0 +1,47 @@
+---
+id: more-resources
+title: 其他参考资源
+---
+
+如果你想继续深入学习,还有很多内容值得探索:开发工作流、发布到应用商店、国际化、安全性等等。
+
+## 接下来可以看什么
+
+- [搭建开发环境](environment-setup)
+- [搭建开发工作流](running-on-device)
+- [设计和布局你的应用](flexbox)
+- [调试你的应用](debugging)
+- [让你的应用支持跨平台](platform-specific-code)
+- [参与 React Native 社区](/community/overview)
+
+## 深入学习
+
+- [React 官方文档](https://react.dev/learn)
+- [MDN 的 JavaScript 教程、参考资料与指南](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
+- [Android](https://developer.android.com/docs) 和 [iOS](https://developer.apple.com/documentation/uikit) 平台文档
+
+## IDE
+
+我们推荐使用 [VS Code](https://code.visualstudio.com/) 编辑器,以及它方便好用的 [React Native 工具](https://marketplace.visualstudio.com/items?itemName=msjsdiag.vscode-react-native)。
+
+## 可尝试的平台
+
+[Expo](https://docs.expo.dev/) 是一套面向 React Native 的工具与服务框架,重点帮助你构建、发布并持续迭代应用,支持类似 Web 开发中常见的预览部署工作流,并能够自动化你的开发流程。Expo 还使你可以在完全不接触 Xcode 或 Android Studio 的情况下构建 React Native 应用;如果你想使用这些工具,它也不会造成阻碍。
+
+[Ignite](https://github.com/infinitered/ignite) 是一个包含多套 React Native 样板工程的入门 CLI。最新版本 Ignite Maverick 使用 MobX-State-Tree 进行状态管理,并集成了 React Navigation 及其他常用库。它内置用于生成 screen、model 等内容的生成器,并且开箱即支持 Expo。Ignite 还附带一个适合自定义设计、主题支持和测试的组件库。如果你正在寻找一套预先配置好的技术栈,Ignite 可能会非常适合你。
+
+## 示例应用
+
+你可以试试 [Showcase](https://reactnative.dev/showcase) 里的应用,看看 React Native 能做到什么!如果你想更亲自动手一些,也可以看看 GitHub 上这组[示例应用](https://github.com/ReactNativeNews/React-Native-Apps)。你可以直接阅读它们的源码——也可以尝试在模拟器或真机上运行其中一个。
+
+## 查找、创建并分享你自己的 Native Components 和 TurboModules
+
+React Native 拥有一个由成千上万像你一样的开发者组成的社区,他们在持续创作内容、工具、教程——以及 Native Components!
+
+如果你在 Core Components 中找不到自己需要的内容,可以访问 [React Native Directory](https://reactnative.directory) 看看社区已经创建了哪些内容。
+
+:::caution
+本文档引用的是一套旧版 API,目前需要更新以反映新架构(New Architecture)。
+:::
+
+想自己创建 Native Component 或 Module 吗?为自己的使用场景编写模块,并通过 NPM 和 GitHub 与他人分享,有助于壮大 React Native 的生态与社区!可以阅读以下指南来创建你自己的 Native Modules([Android](legacy/native-modules-android)、[iOS](legacy/native-modules-ios))以及 Native Components([Android](legacy/native-components-android)、[iOS](legacy/native-components-ios))。
diff --git a/cnwebsite/versioned_docs/version-0.85/native-platforms.md b/cnwebsite/versioned_docs/version-0.85/native-platforms.md
new file mode 100644
index 00000000000..f6094495645
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/native-platforms.md
@@ -0,0 +1,32 @@
+---
+id: native-platform
+title: 桥接原生平台能力
+---
+
+你的应用可能需要访问 React Native 或社区维护的数百个 [第三方库](https://reactnative.directory/) 中未直接提供的平台功能。也许你想要重用一些现有的 Objective-C、Swift、Java、Kotlin 或 C++ 代码。无论你的原因是什么,React Native 都提供了一组强大的 API 来连接你的原生代码和 JavaScript 应用代码。
+
+本指南介绍:
+
+- **原生模块:** 没有用户界面的原生库。例如:持久存储、通知、网络事件。这些可以通过 JavaScript 函数和对象访问。
+- **原生组件:** 原生平台视图、小部件和控制器,通过 React 组件可供你的应用的 JavaScript 代码使用。
+
+:::note
+你可能曾经用过:
+
+- [传统原生模块](./legacy/native-modules-intro);
+- [传统原生 UI 组件](./legacy/native-components-android);
+
+这些是我们即将弃用的原生模块和组件 API。由于我们引入了向后兼容的互操作层,所以你仍然可以继续使用许多这些遗留库。但即便如此,你还是应该考虑:
+
+- 使用替代库,
+- 升级到支持新架构的库,或者
+- 将这些库移植到 Turbo 原生模块或 Fabric 原生组件。
+
+:::
+
+1. Turbo 原生模块
+ - [Android 与 iOS 的原生模块](turbo-native-modules.md)
+ - [使用 C++ 实现跨平台的原生模块](the-new-architecture/pure-cxx-modules.md)
+ - [高级:自定义 C++ 类型](the-new-architecture/custom-cxx-types.md)
+2. Fabric 原生组件
+ - [Android 与 iOS 的原生 UI 组件](fabric-native-components.md)
diff --git a/cnwebsite/versioned_docs/version-0.85/navigation.md b/cnwebsite/versioned_docs/version-0.85/navigation.md
new file mode 100644
index 00000000000..410f5dffb5d
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/navigation.md
@@ -0,0 +1,121 @@
+---
+id: navigation
+title: 使用导航器跳转页面
+---
+
+移动应用基本不会只由一个页面组成。管理多个页面的呈现和切换通常由导航器(navigator)来完成。
+
+本文介绍了 React Native 中可用的各种导航方案。如果你刚开始接触导航功能,推荐使用 [React Navigation](navigation.md#react-navigation)。React Navigation 提供了简洁易用的导航方案,支持在 Android 和 iOS 上实现常见的堆栈导航和标签导航模式。
+
+如果你要将 React Native 集成到已有原生导航管理的应用中,或者想寻找 React Navigation 的替代方案,可以考虑以下库——它在两个平台上都提供了原生导航支持:[react-native-navigation](https://github.com/wix/react-native-navigation)。
+
+## React Navigation
+
+React Navigation 是社区维护的独立导航库,只需几行代码就能配置好应用的页面。
+
+### 快速开始模板
+
+如果你要新建项目,可以使用 React Navigation 模板配合 [Expo](https://expo.dev/) 快速创建:
+
+```shell
+npx create-expo-app@latest --template react-navigation/template
+```
+
+请参阅项目的 `README.md` 了解更多入门信息。
+
+### 安装与配置
+
+首先在项目中安装所需依赖:
+
+```shell
+npm install @react-navigation/native @react-navigation/native-stack
+```
+
+接下来安装所需的对等依赖。根据你的项目类型(Expo 托管项目或纯 React Native 项目),需要执行不同的命令:
+
+- 如果是 Expo 托管项目,使用 `expo` 安装依赖:
+
+ ```shell
+ npx expo install react-native-screens react-native-safe-area-context
+ ```
+
+- 如果是纯 React Native 项目,使用 `npm` 安装依赖:
+
+ ```shell
+ npm install react-native-screens react-native-safe-area-context
+ ```
+
+ 对于纯 React Native 项目的 iOS 端,请确保已安装 [CocoaPods](https://cocoapods.org/)。然后执行以下命令安装 Pod 依赖:
+
+ ```shell
+ cd ios
+ pod install
+ cd ..
+ ```
+
+安装并配置好依赖后,就可以开始在项目中使用 React Navigation 了。
+
+使用 React Navigation 时,你需要在应用中配置[导航器](https://reactnavigation.org/docs/glossary-of-terms#navigator)。导航器负责处理应用中页面之间的切换,并提供头部栏、标签栏等 UI 组件。
+
+现在你可以在设备/模拟器上构建并运行应用了。
+
+### 使用方法
+
+下面是一个包含首页和个人资料页的示例:
+
+```tsx
+import * as React from 'react';
+import {createStaticNavigation} from '@react-navigation/native';
+import {createNativeStackNavigator} from '@react-navigation/native-stack';
+
+const RootStack = createNativeStackNavigator({
+ screens: {
+ Home: {
+ screen: HomeScreen,
+ options: {title: 'Welcome'},
+ },
+ Profile: {
+ screen: ProfileScreen,
+ },
+ },
+});
+
+const Navigation = createStaticNavigation(RootStack);
+
+export default function App() {
+ return ;
+}
+```
+
+在此示例中,`RootStack` 是通过 `createNativeStackNavigator` 创建的导航器,其 `screens` 属性中定义了 2 个页面(`Home` 和 `Profile`)。你可以按同样的方式定义任意数量的页面。
+
+每个页面可以在 `options` 属性中指定配置项,例如页面标题。每个页面定义还需要一个 `screen` 属性,值为 React 组件或另一个导航器。
+
+在页面组件内部,可以使用 `useNavigation` Hook 获取 `navigation` 对象,该对象提供了跳转到其他页面的各种方法。例如,使用 `navigation.navigate` 跳转到 `Profile` 页面:
+
+```tsx
+import {useNavigation} from '@react-navigation/native';
+
+function HomeScreen() {
+ const navigation = useNavigation();
+
+ return (
+
+ navigation.navigate('Profile', {name: 'Jane'})
+ }
+ />
+ );
+}
+
+function ProfileScreen({route}) {
+ return This is {route.params.name}'s profile ;
+}
+```
+
+这个 `native-stack` 导航器使用了原生 API:iOS 上的 `UINavigationController` 和 Android 上的 `Fragment`,因此使用 `createNativeStackNavigator` 构建的导航在行为和性能表现上与基于这些 API 原生构建的应用一致。
+
+React Navigation 还提供了标签导航、抽屉导航等不同类型的导航器包。你可以使用它们在应用中实现各种导航模式。
+
+要全面了解 React Navigation,请参阅 [React Navigation 入门指南](https://reactnavigation.org/docs/getting-started)。
diff --git a/cnwebsite/versioned_docs/version-0.85/netinfo.md b/cnwebsite/versioned_docs/version-0.85/netinfo.md
new file mode 100644
index 00000000000..92d81573ddd
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/netinfo.md
@@ -0,0 +1,166 @@
+---
+id: netinfo
+title: NetInfo
+---
+
+> **已过时。** Use [react-native-community/react-native-netinfo](https://github.com/react-native-community/react-native-netinfo) instead.
+
+通过 NetInfo 模块可以获取设备当前的联网状态。
+
+```
+NetInfo.getConnectionInfo().then((connectionInfo) => {
+ console.log('Initial, type: ' + connectionInfo.type + ', effectiveType: ' + connectionInfo.effectiveType);
+});
+function handleFirstConnectivityChange(connectionInfo) {
+ console.log('First change, type: ' + connectionInfo.type + ', effectiveType: ' + connectionInfo.effectiveType);
+ NetInfo.removeEventListener(
+ 'connectionChange',
+ handleFirstConnectivityChange
+ );
+}
+NetInfo.addEventListener(
+ 'connectionChange',
+ handleFirstConnectivityChange
+);
+```
+
+### ConnectionType 枚举值
+
+`ConnectionType`描述了设备联网的方式。
+
+`ConnectionType`有如下跨平台可用的值:
+
+- `none` - 设备处于离线状态
+- `wifi` - 设备通过 wifi 联网,或者设备是 iOS 模拟器
+- `cellular` - 设备通过蜂窝数据流量联网
+- `unknown` - 联网状态异常
+
+`ConnectionType`还有如下仅在 Android 平台上可用的值:
+
+- `bluetooth` - 设备通过蓝牙协议联网
+- `ethernet` - 设备通过以太网协议联网
+- `wimax` - 设备通过 WiMAX 协议联网
+
+### EffectiveConnectionType 枚举值
+
+`EffectiveConnectionType`有如下跨平台可用的值:
+
+- `2g`
+- `3g`
+- `4g`
+- `unknown`
+
+### Android
+
+要在 Android 上获取联网状态,还需要在`AndroidManifest.xml`中添加如下权限请求:
+
+` `
+
+### 查看方法
+
+- [`addEventListener`](netinfo.md#addeventlistener)
+- [`removeEventListener`](netinfo.md#removeeventlistener)
+- [`getConnectionInfo`](netinfo.md#getconnectioninfo)
+- [`isConnectionExpensive`](netinfo.md#isconnectionexpensive)
+
+### 查看属性
+
+- [`isConnected`](netinfo.md#isconnected)
+
+---
+
+# 文档
+
+## 方法
+
+### `addEventListener()`
+
+```jsx
+NetInfo.addEventListener(eventName, handler);
+```
+
+添加一个事件监听函数。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| --------- | ------------------------------ | ---- | -------- |
+| eventName | enum(connectionChange, change) | 是 | 事件名 |
+| handler | function | 是 | 监听函数 |
+
+支持的事件名:
+
+- `connectionChange`:当联网状态改变时触发。传给监听函数的参数是一个对象,包含有下列属性:
+ - `type`: 上面所列出的`ConnectionType`值
+ - `effectiveType`: 上面所列出的`EffectiveConnectionType`值
+- `change`: 这一事件已过时。请使用`connectionChange`代替。当联网状态改变时触发。
+
+---
+
+### `removeEventListener()`
+
+```jsx
+NetInfo.removeEventListener(eventName, handler);
+```
+
+移除联网状态改变的监听函数。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| --------- | ------------------------------ | ---- | -------- |
+| eventName | enum(connectionChange, change) | 是 | 事件名 |
+| handler | function | 是 | 监听函数 |
+
+---
+
+### `getConnectionInfo()`
+
+```jsx
+NetInfo.getConnectionInfo();
+```
+
+返回一个 promise,最终解析值为带有`type`和`effectiveType`属性的对象。其中`type`属性的值为[`ConnectionType`](netinfo.md#connectiontype-enum) ,而`effectiveType`属性的值为[`EffectiveConnectionType`](netinfo.md#effectiveconnectiontype-enum))。
+
+---
+
+### `isConnectionExpensive()`
+
+```jsx
+NetInfo.isConnectionExpensive();
+```
+
+仅 Android 可用。用于判断当前活动的连接是否计费。如果当前连接是通过移动数据网络,或者通过基于移动数据网络所创建的 wifi 热点,或是大量消耗电池等等,都有可能被判定为计费的数据连接。
+
+```
+NetInfo.isConnectionExpensive()
+.then(isConnectionExpensive => {
+ console.log('Connection is ' + (isConnectionExpensive ? 'Expensive' : 'Not Expensive'));
+})
+.catch(error => {
+ console.error(error);
+});
+```
+
+## 属性
+
+### `isConnected`
+
+在所有平台上可用。以异步方式获取一个布尔值,用于判断当前设备是否联网。
+
+```
+NetInfo.isConnected.fetch().then(isConnected => {
+ console.log('First, is ' + (isConnected ? 'online' : 'offline'));
+});
+function handleFirstConnectivityChange(isConnected) {
+ console.log('Then, is ' + (isConnected ? 'online' : 'offline'));
+ NetInfo.isConnected.removeEventListener(
+ 'connectionChange',
+ handleFirstConnectivityChange
+ );
+}
+NetInfo.isConnected.addEventListener(
+ 'connectionChange',
+ handleFirstConnectivityChange
+);
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/network.md b/cnwebsite/versioned_docs/version-0.85/network.md
new file mode 100644
index 00000000000..1d8828457d8
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/network.md
@@ -0,0 +1,298 @@
+---
+id: network
+title: 访问网络
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+很多移动应用都需要从远程地址中获取数据或资源。你可能需要给某个 REST API 发起 POST 请求以提交用户数据,又或者可能仅仅需要从某个服务器上获取一些静态内容——以下就是你会用到的东西。新手可以对照这个[简短的视频教程](http://v.youku.com/v_show/id_XMTUyNTEwMTA5Ng==.html)加深理解。
+
+## 使用 Fetch
+
+React Native 提供了和 web 标准一致的[Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API),用于满足开发者访问网络的需求。如果你之前使用过`XMLHttpRequest`(即俗称的 ajax)或是其他的网络 API,那么 Fetch 用起来将会相当容易上手。这篇文档只会列出 Fetch 的基本用法,并不会讲述太多细节,你可以使用你喜欢的搜索引擎去搜索`fetch api`关键字以了解更多信息。
+
+### 发起请求
+
+要从任意地址获取内容的话,只需简单地将网址作为参数传递给 fetch 方法即可(fetch 这个词本身也就是`获取`的意思):
+
+```tsx
+fetch('https://mywebsite.com/mydata.json');
+```
+
+Fetch 还有可选的第二个参数,可以用来定制 HTTP 请求一些参数。你可以指定 header 参数,或是指定使用 POST 方法,又或是提交数据等等:
+
+```tsx
+fetch('https://mywebsite.com/endpoint/', {
+ method: 'POST',
+ headers: {
+ Accept: 'application/json',
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ firstParam: 'yourValue',
+ secondParam: 'yourOtherValue',
+ }),
+});
+```
+
+提交数据的格式关键取决于 headers 中的`Content-Type`。`Content-Type`有很多种,对应 body 的格式也有区别。到底应该采用什么样的`Content-Type`取决于服务器端,所以请和服务器端的开发人员沟通确定清楚。常用的'Content-Type'除了上面的'application/json',还有传统的网页表单形式,示例如下:
+
+```js
+fetch('https://mywebsite.com/endpoint/', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ body: 'key1=value1&key2=value2',
+});
+```
+
+可以参考[Fetch 请求文档](https://developer.mozilla.org/en-US/docs/Web/API/Request)来查看所有可用的参数。
+
+> 注意:使用 Chrome 调试目前无法观测到 React Native 中的网络请求,你可以使用第三方的[react-native-debugger](https://github.com/jhen0409/react-native-debugger)来进行观测。
+
+### 处理服务器的响应数据
+
+上面的例子演示了如何发起请求。很多情况下,你还需要处理服务器回复的数据。
+
+网络请求天然是一种异步操作。Fetch 方法会返回一个[Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise),这种模式可以简化异步风格的代码(译注:同样的,如果你不了解 promise,建议使用搜索引擎补课):
+
+```tsx
+const getMoviesFromApi = () => {
+ return fetch('https://reactnative.dev/movies.json')
+ .then(response => response.json())
+ .then(json => {
+ return json.movies;
+ })
+ .catch(error => {
+ console.error(error);
+ });
+};
+```
+
+你也可以在 React Native 应用中使用`async`/`await` 语法:
+
+```tsx
+const getMoviesFromApiAsync = async () => {
+ try {
+ const response = await fetch(
+ 'https://reactnative.dev/movies.json',
+ );
+ const json = await response.json();
+ return json.movies;
+ } catch (error) {
+ console.error(error);
+ }
+};
+```
+
+别忘了 catch 住`fetch`可能抛出的异常,否则出错时你可能看不到任何提示。
+
+
+
+
+```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 {
+ 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&ext=tsx
+import React, {useEffect, useState} from 'react';
+import {ActivityIndicator, FlatList, Text, View} from 'react-native';
+
+type Movie = {
+ id: string;
+ title: string;
+ releaseYear: string;
+};
+
+type MoviesResponse = {
+ title: string;
+ description: string;
+ movies: Movie[];
+};
+
+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()) as MoviesResponse;
+ 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;
+```
+
+
+
+
+:::info
+默认情况下,iOS 9.0 或更高版本会强制执行 App Transport Security (ATS)。ATS 要求所有 HTTP 连接使用 HTTPS。如果你需要从明文 URL(以`http`开头的 URL)获取数据,你需要先[添加 ATS 例外](integration-with-existing-apps.md#test-your-integration)。如果你提前知道需要访问哪些域名,只为这些域名添加例外会更安全;如果域名在运行时才知道,你可以[完全禁用 ATS](publishing-to-app-store.md#1-enable-app-transport-security)。但请注意,从 2017 年 1 月起,[Apple App Store 审核将要求对禁用 ATS 提供合理理由](https://forums.developer.apple.com/thread/48979)。更多信息请参阅 [Apple 文档](https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CocoaKeys.html#//apple_ref/doc/uid/TP40009251-SW33)。
+:::
+
+:::tip
+在 Android 上,从 API Level 28 开始,默认也会阻止明文流量。可以通过在 app manifest 文件中设置[`android:usesCleartextTraffic`](https://developer.android.com/guide/topics/manifest/application-element#usesCleartextTraffic)来覆盖此行为。
+:::
+
+## 使用其他的网络库
+
+React Native 中已经内置了[XMLHttpRequest API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest)(也就是俗称的 ajax)。一些基于 XMLHttpRequest 封装的第三方库也可以使用,例如[frisbee](https://github.com/niftylettuce/frisbee)或是[axios](https://github.com/mzabriskie/axios)等。但注意不能使用 jQuery,因为 jQuery 中还使用了很多浏览器中才有而 RN 中没有的东西(所以也不是所有 web 中的 ajax 库都可以直接使用)。
+
+```tsx
+const request = new XMLHttpRequest();
+request.onreadystatechange = e => {
+ if (request.readyState !== 4) {
+ return;
+ }
+
+ if (request.status === 200) {
+ console.log('success', request.responseText);
+ } else {
+ console.warn('error');
+ }
+};
+
+request.open('GET', 'https://mywebsite.com/endpoint/');
+request.send();
+```
+
+:::warning 注意
+XMLHttpRequest 的安全模型与网页不同,因为在原生应用中没有[跨域](https://en.wikipedia.org/wiki/Cross-origin_resource_sharing)的概念。
+:::
+
+## WebSocket 支持
+
+React Native 还支持[WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSocket),这种协议可以在单个 TCP 连接上提供全双工的通信信道。
+
+```tsx
+const ws = new WebSocket('ws://host.com/path');
+
+ws.onopen = () => {
+ // connection opened
+ ws.send('something'); // send a message
+};
+
+ws.onmessage = e => {
+ // a message was received
+ console.log(e.data);
+};
+
+ws.onerror = e => {
+ // an error occurred
+ console.log(e.message);
+};
+
+ws.onclose = e => {
+ // connection closed
+ console.log(e.code, e.reason);
+};
+```
+
+## 使用 `fetch` 和基于 cookie 的身份验证存在已知问题
+
+目前,以下选项在 `fetch` 中无法正常工作:
+
+- `redirect:manual`
+- `credentials:omit`
+
+* 在 Android 上重复使用相同名称的标头将导致仅存在最新的标头。您可以在此处找到一个临时解决方案:https://github.com/facebook/react-native/issues/18837#issuecomment-398779994。
+* 基于 cookie 的身份验证目前不稳定。您可以在此处查看引发的一些问题:https://github.com/facebook/react-native/issues/23185
+* 在 iOS 上,至少在通过 `302` 重定向时,如果存在 `Set-Cookie` 标头,则 cookie 不会正确设置。由于无法手动处理重定向,由过期会话引起的重定向可能会导致无限请求的死循环发生。
+
+## 在 iOS 上配置 NSURLSession
+
+对于一些应用程序,为在运行在 iOS 上的 React Native 应用程序中用于网络请求的底层`NSURLSession`提供自定义的`NSURLSessionConfiguration`可能是合适的。例如,可能需要为所有来自应用程序的网络请求设置自定义用户代理字符串,或者使用一个短暂的`NSURLSessionConfiguration`提供给`NSURLSession`。函数`RCTSetCustomNSURLSessionConfigurationProvider`允许进行这样的定制。记得在调用`RCTSetCustomNSURLSessionConfigurationProvider`的文件中添加以下导入:
+
+```objectivec
+#import
+```
+
+`RCTSetCustomNSURLSessionConfigurationProvider` 应在应用程序生命周期的早期调用,以便在 React 需要时可以轻松访问,例如:
+
+```objectivec
+-(void)application:(__unused UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ // set RCTSetCustomNSURLSessionConfigurationProvider
+ RCTSetCustomNSURLSessionConfigurationProvider(^NSURLSessionConfiguration *{
+ NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
+ // configure the session
+ return configuration;
+ });
+ // set up React
+ _bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
+}
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/new-architecture-app-intro.md b/cnwebsite/versioned_docs/version-0.85/new-architecture-app-intro.md
new file mode 100644
index 00000000000..08e126ae96b
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/new-architecture-app-intro.md
@@ -0,0 +1,124 @@
+---
+id: new-architecture-app-intro
+title: 在应用中启用的预备工作
+---
+
+import NewArchitectureWarning from './\_markdown-new-architecture-warning.mdx';
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import constants from '@site/core/TabsConstants';
+
+
+
+在启用新架构之前,应先满足一些先决条件。
+
+## 更新至最新版 React Native
+
+React Native 在 0.68.0 版本中发布了对新架构的支持。
+
+本指南的撰写是基于你使用的是 [**最新发布**的 React Native 版本](https://github.com/facebook/react-native/releases/latest)。
+
+你可以在[升级到新版本](/docs/upgrading)页面找到升级说明。
+
+升级后记得重新安装依赖(运行`npm install`或`yarn`)。
+
+:::info
+
+每当你需要重命名`ios`文件夹中的某些文件时,请**使用 Xcode 重命名它们**。这可确保 Xcode 工程中的文件引用也会更新。你可能需要先清理构建文件夹(**Project**→**Clean Build Folder**或Cmd ⌘ + Shift ⇪ + K ),然后重新构建应用。如果文件是在 Xcode 之外重命名的,你可能需要点击旧的`.m`文件引用,并定位到新文件。
+
+:::
+
+## Android - 启用新架构
+
+如果你已成功将项目更新到最新版本的 React Native,那么你**已经满足**在 Android 上使用新架构的所有先决条件。
+
+你只需要按如下方式更新`android/gradle.properties`文件:
+
+```diff
+# 使用此属性启用对新架构的支持。
+# 这将允许你在应用中使用TurboModules和Fabric渲染器。
+# 如果你想编写自定义TurboModules/Fabric组件或使用提供它们的库,
+# 你应该启用此标志。
+-newArchEnabled=false
++newArchEnabled=true
+```
+
+## iOS - 启用新架构
+
+如果你已成功将项目更新到最新版 React Native,那么你**已经满足**在 iOS 上使用新架构的所有先决条件。
+
+你只需通过运行带有正确标志的`pod install`来重新安装 pods:
+
+```bash
+# 运行带标志的pod install:
+RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
+```
+
+## 运行应用
+
+现在是时候运行应用以验证一切正常了:
+
+
+
+
+```bash
+# 运行Android
+yarn android
+
+# 运行iOS
+yarn ios
+```
+
+
+
+
+```bash
+# 运行Android
+npm run android
+
+# 运行iOS
+npm run ios
+```
+
+
+
+
+在你的 Metro 终端日志中,你现在会看到以下日志,确认 Fabric 正在正确运行:
+
+```
+BUNDLE ./App.tsx
+LOG Running "App" with {"fabric":true,"initialProps":{"concurrentRoot": "true"},"rootTag":1}
+```
+
+## 高级 - 在互操作层中传递你的组件
+
+如果你按照前面的步骤操作,但你的应用使用了一些尚未完全迁移到新架构的自定义本地组件,你会看到一些红色/粉色框,说明该组件与 Fabric 不兼容。这是因为为旧架构编写的自定义本地组件无法在新架构中原封不动地运行。
+
+从**React Native 0.72.0**开始,我们在互操作层上做了一些工作,让你不需要等待它们迁移到新架构的情况下,就可以在新架构中使用遗留组件。
+
+你可以阅读更多关于互操作层及如何使用它的内容[这里](https://github.com/reactwg/react-native-new-architecture/discussions/135)。按照该指南注册你的组件,然后使用以下命令重新运行应用:
+
+
+
+
+```bash
+# To run android
+yarn android
+
+# To run iOS
+yarn ios
+```
+
+
+
+
+```bash
+# To run android
+npm run android
+
+# To run iOS
+npm run ios
+```
+
+
+
diff --git a/cnwebsite/versioned_docs/version-0.85/new-architecture-app-renderer-ios.md b/cnwebsite/versioned_docs/version-0.85/new-architecture-app-renderer-ios.md
new file mode 100644
index 00000000000..c4f97d09d31
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/new-architecture-app-renderer-ios.md
@@ -0,0 +1,90 @@
+---
+id: new-architecture-app-renderer-ios
+title: 在 iOS 上启用 Fabric
+---
+
+import NewArchitectureWarning from './\_markdown-new-architecture-warning.mdx';
+
+
+
+This section will go over how to enable the new renderer in your app. Make sure your application meets all the [prerequisites](new-architecture-app-intro).
+
+## 1. Enable Fabric in Podfile
+
+Add changes to your Podfile. You can see some examples in [RNTester](https://github.com/facebook/react-native/blob/main/packages/rn-tester/Podfile) and [rn-demo-app](https://github.com/facebook/fbt/blob/rn-demo-app/ios/Podfile).
+
+```ruby title="Podfile"
+# Add the following line at the top of Podfile.
+# Codegen produces files/classes that share names, and it will show the warning.
+# deterministic_uuids option surpresses the warning.
+install! 'cocoapods', :deterministic_uuids => false
+target 'Some App' do
+ pods()
+end
+def pods()
+ # Get config
+ config = use_native_modules!
+ # Use env variables to turn it on/off.
+ fabric_enabled = ENV['USE_FABRIC']
+ use_react_native!(
+ ...
+ # Modify here if your app root path isn't the same as this one.
+ :app_path => "#{Dir.pwd}/..",
+ # Pass the flag to enable fabric to use_react_native!.
+ :fabric_enabled => fabric_enabled
+ )
+end
+```
+
+## 2. Update your root view
+
+How to render your app with Fabric depends on your setup. Here is an example of how you can enable Fabric in your app with the `RN_FABRIC_ENABLED` compiler flag to enable/disable. Refer [RN-Tester’s AppDelegate](https://github.com/facebook/react-native/blob/main/packages/rn-tester/RNTester/AppDelegate.mm) as an example.
+
+```objc title="AppDelegate.mm"
+#ifdef RN_FABRIC_ENABLED
+#import
+#import
+#import
+#import
+#endif
+
+@interface AppDelegate () {
+#ifdef RN_FABRIC_ENABLED
+ RCTSurfacePresenterBridgeAdapter *_bridgeAdapter;
+ std::shared_ptr _reactNativeConfig;
+ facebook::react::ContextContainer::Shared _contextContainer;
+#endif
+
+ // Find a line that define rootView and replace/edit with the following lines.
+
+#ifdef RN_FABRIC_ENABLED
+ _contextContainer = std::make_shared();
+ _reactNativeConfig = std::make_shared();
+
+ _contextContainer->insert("ReactNativeConfig", _reactNativeConfig);
+
+ _bridgeAdapter = [[RCTSurfacePresenterBridgeAdapter alloc]
+ initWithBridge:bridge
+ contextContainer:_contextContainer];
+
+ bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
+
+ UIView *rootView =
+ [[RCTFabricSurfaceHostingProxyRootView alloc] initWithBridge:bridge
+ moduleName:<#moduleName#>
+ initialProperties:@{}];
+#else
+ // Current implementation to define rootview.
+ RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
+ moduleName:<#moduleName#>
+ initialProperties:@{}];
+#endif
+```
+
+## 3. Run pod install
+
+```bash
+// Run pod install with the flags
+USE_FABRIC=1 RCT_NEW_ARCH_ENABLED=1 pod install
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/new-architecture-library-android.md b/cnwebsite/versioned_docs/version-0.85/new-architecture-library-android.md
new file mode 100644
index 00000000000..49d4b77d70c
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/new-architecture-library-android.md
@@ -0,0 +1,118 @@
+---
+id: new-architecture-library-android
+title: 在 Android 库中启用
+---
+
+import NewArchitectureWarning from './\_markdown-new-architecture-warning.mdx'; import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+
+
+一旦您在[先决条件](new-architecture-library-intro)中定义了本机模块的 JavaScript 规范,设置了 CodeGen 配置,并遵循了 Android/Gradle 设置,然后就可以将您的库迁移到新架构。以下是迁移所需的步骤。
+
+## 1. 扩展或实现代码生成的本地接口
+
+您为原生模块或组件定义的 JavaScript 规范将用于为每个支持的平台(即 Android 和 iOS)生成本地接口代码。这些本地接口文件将在构建依赖于您的库的反应应用程序时**生成**。
+
+虽然这种生成的本地接口代码**不会作为您图书馆的一部分进行运输**,但您确实需要确保您的 Java / Kotlin 代码符合这些本地接口文件提供的协议。
+
+您可以调用`generateCodegenArtifactsFromSchema` Gradle 任务来为您的库生成本机接口代码,以便将其用作**参考:**
+
+```bash
+./gradlew generateCodegenArtifactsFromSchema
+```
+
+The files that are output can be found inside `build/generated/source/codegen` and **should not be committed**, but you’ll need to refer to them to determine what changes you need to make to your native modules in order for them to provide an implementation for each generated interface.
+
+The output of the Codegen for a module called `NativeAwesomeManager` will look like this:
+
+```
+app/build/generated/source/codegen
+├── java
+│ └── com
+│ └── example
+│ └── samplelibrary
+│ └── NativeAwesomeManagerSpec.java
+├── jni
+│ ├── Android.mk
+│ ├── CMakeLists.txt
+│ ├── react
+│ │ └── renderer
+│ │ └── components
+│ │ └── samplelibrary
+│ │ ├── ComponentDescriptors.h
+│ │ ├── EventEmitters.cpp
+│ │ ├── EventEmitters.h
+│ │ ├── Props.cpp
+│ │ ├── Props.h
+│ │ ├── ShadowNodes.cpp
+│ │ └── ShadowNodes.h
+│ ├── samplelibrary-generated.cpp
+│ └── samplelibrary.h
+└── schema.json
+```
+
+### Extends the Abstract Class Provided by the Codegen
+
+Update your native module or component to ensure it **extends the abstract class** that has been code-generated from your JavaScript specs (i.e., the `NativeAwesomeManagerSpec.java` file from the previous example).
+
+Following the example set forth in the previous section, your library might import `NativeAwesomeManagerSpec`, implement the relevant native interface and the necessary methods for it:
+
+
+
+
+
+```java
+import androidx.annotation.NonNull;
+
+import com.example.samplelibrary.NativeAwesomeManagerSpec;
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.ReactApplicationContext;
+
+public class NativeAwesomeManager extends NativeAwesomeManagerSpec {
+
+ public static final String NAME = "NativeAwesomeManager";
+
+ public NativeAwesomeManager(ReactApplicationContext reactContext) {
+ super(reactContext);
+ }
+
+ @Override
+ public void getString(String id, Promise promise) {
+ // Implement this method
+ }
+
+ @NonNull
+ @Override
+ public String getName() {
+ return NAME;
+ }
+}
+```
+
+
+
+
+
+```kotlin
+import com.example.samplelibrary.NativeAwesomeManagerSpec
+import com.facebook.react.bridge.Promise
+import com.facebook.react.bridge.ReactApplicationContext
+
+class NativeAwesomeManager(reactContext: ReactApplicationContext) :
+ NativeAwesomeManagerSpec(reactContext) {
+ override fun getString(id: String, promise: Promise) {
+ // Implement this method
+ }
+
+ override fun getName() = NAME
+
+ companion object {
+ val NAME = "NativeAwesomeManager"
+ }
+}
+```
+
+
+
+
+Please note that the **generated abstract class** that you’re now extending (`MyAwesomeSpec` in this example) is itself extending `ReactContextBaseJavaModule`. Therefore you should not lose access to any of the method/fields you were previously using (e.g., the `ReactApplicationContext` and so on). Moreover, the generated class will now also implement the `TurboModule` interface for you.
diff --git a/cnwebsite/versioned_docs/version-0.85/new-architecture-turbo-module.md b/cnwebsite/versioned_docs/version-0.85/new-architecture-turbo-module.md
new file mode 100644
index 00000000000..1a1381ae48b
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/new-architecture-turbo-module.md
@@ -0,0 +1,900 @@
+---
+id: new-architecture-turbo-modules
+title: 新架构的原生模块(Turbo Module)
+---
+
+# Turbo 原生模块
+
+If you've worked with React Native, you may be familiar with the concept of [Native Modules](https://reactnative.dev/docs/native-modules-intro), which allow JavaScript and platform-native code to communicate over the React Native "bridge", which handles cross-platform serialization via JSON.
+
+Turbo Native Modules are the next iteration on Native Modules that provide a few extra [benefits](https://reactnative.dev/docs/the-new-architecture/landing-page):
+
+- Strongly typed interfaces that are consistent across platforms
+- The ability to write your code in C++, either exclusively or integrated with another native platform language, reducing the need to duplicate implementations across platforms
+- Lazy loading of modules, allowing for faster app startup
+- The use of JSI, a JavaScript interface for native code, allows for more efficient communication between native and JavaScript code than the bridge
+
+At a high-level the steps for writing a Turbo Module are:
+
+1. Define a JavaScript specification using Flow or TypeScript.
+1. Configure the dependencies management system to generate code from the provided spec.
+1. Implement the Native code.
+1. Integrate the code in the app.
+
+This guide will show you how to create a basic Turbo Native Module compatible with the latest version of React Native.
+
+> [!Note]
+> You can also setup local library containing Turbo Native Module with one command. Read the guide to [Local libraries setup](https://reactnative.dev/docs/next/local-library-setup) for more details.
+
+## How to Create a Turbo Native Module
+
+To create a Turbo Native Module, we need to:
+
+1. Define the JavaScript specification.
+2. Configure the module so that Codegen can generate the scaffolding.
+3. Write the native code to finish implementing the module.
+
+## 1. Folder Setup
+
+In order to keep the module decoupled from the app, it's a good idea to define the module separately from the app and then add it as a dependency to your app later. This is also what you'll do for writing Turbo Native Modules that can be released as open-source libraries later.
+
+Next to your application, create a folder called `RTNCalculator`. **RTN** stands for "**R**eac**t** **N**ative", and is a recommended prefix for React Native modules.
+
+Within `RTNCalculator`, create three subfolders: `js`, `ios`, and `android`.
+
+The final result should look like this:
+
+```sh
+TurboModulesGuide
+├── MyApp
+└── RTNCalculator
+ ├── android
+ ├── ios
+ └── js
+```
+
+## 2. JavaScript Specification
+
+The **New Architecture** requires interfaces specified in a typed dialect of JavaScript (either [Flow](https://flow.org/) or [TypeScript](https://www.typescriptlang.org/)). **Codegen** will use these specifications to generate code in strongly-typed languages, including C++, Objective-C++, and Java.
+
+There are two requirements the file containing this specification must meet:
+
+1. The file **must** be named `Native`, with a `.js` or `.jsx` extension when using Flow, or a `.ts`, or `.tsx` extension when using TypeScript. Codegen will only look for files matching this pattern.
+2. The file must export a `TurboModuleRegistrySpec` object.
+
+
+ Flow
+
+```typescript title="NativeCalculator.js"
+// @flow
+import type {TurboModule} from 'react-native/Libraries/TurboModule/RCTExport';
+import {TurboModuleRegistry} from 'react-native';
+
+export interface Spec extends TurboModule {
+ add(a: number, b: number): Promise;
+}
+export default (TurboModuleRegistry.get(
+ 'RTNCalculator'
+): ?Spec);
+```
+
+
+
+
+ TypeScript
+
+```typescript title="NativeCalculator.ts"
+import {TurboModule, TurboModuleRegistry} from 'react-native';
+
+export interface Spec extends TurboModule {
+ add(a: number, b: number): Promise;
+}
+
+export default TurboModuleRegistry.get(
+ 'RTNCalculator',
+) as Spec | null;
+```
+
+
+
+At the beginning of the spec files are the imports:
+
+- The `TurboModule` type, which defines the base interface for all Turbo Native Modules
+- The `TurboModuleRegistry` JavaScript module, which contains functions for loading Turbo Native Modules
+
+The second section of the file contains the interface specification for the Turbo Native Module. In this case, the interface defines the `add` function, which takes two numbers and returns a promise that resolves to a number. This interface type **must** be named `Spec` for a Turbo Native Module.
+
+Finally, we invoke `TurboModuleRegistry.get`, passing the module's name, which will load the Turbo Native Module if it's available.
+
+> [!Warning]
+> We are writing JavaScript files importing types from libraries, without setting up a proper node module and installing its dependencies. Your IDE will not be able to resolve the import statements and you may see errors and warnings. This is expected and will not cause problems when you add the module to your app.
+
+## 3. Module Configuration
+
+Next, you need to add some configuration for [**Codegen**](the-new-architecture/using-codegen) and auto-linking.
+
+Some configuration files are shared between iOS and Android, while the others are platform-specific.
+
+### Shared
+
+The shared configuration is a `package.json` file used by yarn when installing your module. Create the `package.json` file in the root of the `RTNCalculator` directory.
+
+```json title="package.json"
+{
+ "name": "rtn-calculator",
+ "version": "0.0.1",
+ "description": "Add numbers with Turbo Native Modules",
+ "react-native": "js/index",
+ "source": "js/index",
+ "files": [
+ "js",
+ "android",
+ "ios",
+ "rtn-calculator.podspec",
+ "!android/build",
+ "!ios/build",
+ "!**/__tests__",
+ "!**/__fixtures__",
+ "!**/__mocks__"
+ ],
+ "keywords": ["react-native", "ios", "android"],
+ "repository": "https://github.com//rtn-calculator",
+ "author": " (https://github.com/)",
+ "license": "MIT",
+ "bugs": {
+ "url": "https://github.com//rtn-calculator/issues"
+ },
+ "homepage": "https://github.com//rtn-calculator#readme",
+ "devDependencies": {},
+ "peerDependencies": {
+ "react": "*",
+ "react-native": "*"
+ },
+ "codegenConfig": {
+ "name": "RTNCalculatorSpec",
+ "type": "modules",
+ "jsSrcsDir": "js",
+ "android": {
+ "javaPackageName": "com.rtncalculator"
+ }
+ }
+}
+```
+
+The upper part of the file contains some descriptive information like the name of the component, its version, and its source files. Make sure to update the various placeholders which are wrapped in `<>`: replace all the occurrences of the ``, ``, and `` tokens.
+
+Then there are the dependencies for this package. For this guide, you need `react` and `react-native`.
+
+Finally, the **Codegen** configuration is specified by the `codegenConfig` field. It contains an object that defines the module through four fields:
+
+- `name`: The name of the library. By convention, you should add the `Spec` suffix.
+- `type`: The type of module contained by this package. In this case, it is a Turbo Native Module; thus, the value to use is `modules`.
+- `jsSrcsDir`: the relative path to access the `js` specification that is parsed by **Codegen**.
+- `android.javaPackageName`: the package to use in the Java files generated by **Codegen**.
+
+### iOS: Create the `podspec` file
+
+For iOS, you'll need to create a `rtn-calculator.podspec` file, which will define the module as a dependency for your app. It will stay in the root of `RTNCalculator`, alongside the `ios` folder.
+
+The file will look like this:
+
+```ruby title="rtn-calculator.podspec"
+require "json"
+
+package = JSON.parse(File.read(File.join(__dir__, "package.json")))
+
+Pod::Spec.new do |s|
+ s.name = "rtn-calculator"
+ s.version = package["version"]
+ s.summary = package["description"]
+ s.description = package["description"]
+ s.homepage = package["homepage"]
+ s.license = package["license"]
+ s.platforms = { :ios => "11.0" }
+ s.author = package["author"]
+ s.source = { :git => package["repository"], :tag => "#{s.version}" }
+
+ s.source_files = "ios/**/*.{h,m,mm,swift}"
+
+ install_modules_dependencies(s)
+end
+```
+
+The `.podspec` file has to be a sibling of the `package.json` file, and its name is the one we set in the `package.json`'s `name` property: `rtn-calculator`.
+
+The first part of the file prepares some variables that we use throughout the file. Then, there is a section that contains some information used to configure the pod, like its name, version, and description.
+
+All the requirements for the New Architecture have been encapsulated in the [`install_modules_dependencies`](https://github.com/facebook/react-native/blob/main/packages/react-native/scripts/react_native_pods.rb#L198). It takes care of installing the proper dependencies based on which architecture is currently enabled. It also automatically installs the `React-Core` dependency in the old architecture.
+
+### Android: `build.gradle` and `ReactPackage` class
+
+To prepare Android to run **Codegen** you have to:
+
+1. Update the `build.gradle` file.
+2. A Java/Kotlin class that implements the `ReactPackage` interface
+
+At the end of these steps, the `android` folder should look like this:
+
+```title="Android Folder Structure"
+android
+├── build.gradle
+└── src
+ └── main
+ └── java
+ └── com
+ └── rtncalculator
+ └── CalculatorPackage.java
+```
+
+#### The `build.gradle` file
+
+First, create a `build.gradle` file in the `android` folder, with the following contents:
+
+
+ Java
+
+```java title="build.gradle"
+buildscript {
+ ext.safeExtGet = {prop, fallback ->
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
+ }
+ repositories {
+ google()
+ gradlePluginPortal()
+ }
+ dependencies {
+ classpath("com.android.tools.build:gradle:7.3.1")
+ }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'com.facebook.react'
+
+android {
+ compileSdkVersion safeExtGet('compileSdkVersion', 33)
+ namespace "com.rtncalculator"
+}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+dependencies {
+ implementation 'com.facebook.react:react-native'
+}
+```
+
+
+
+
+ Kotlin
+
+```kotlin title="build.gradle"
+buildscript {
+ ext.safeExtGet = {prop, fallback ->
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
+ }
+ repositories {
+ google()
+ gradlePluginPortal()
+ }
+ dependencies {
+ classpath("com.android.tools.build:gradle:7.3.1")
+ classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.22")
+ }
+}
+
+apply plugin: 'com.android.library'
+apply plugin: 'com.facebook.react'
+apply plugin: 'org.jetbrains.kotlin.android'
+
+android {
+ compileSdkVersion safeExtGet('compileSdkVersion', 33)
+ namespace "com.rtncalculator"
+}
+
+repositories {
+ mavenCentral()
+ google()
+}
+
+dependencies {
+ implementation 'com.facebook.react:react-native'
+}
+```
+
+
+
+#### The `ReactPackage` class
+
+Then, you need a class that extends the `TurboReactPackage` interface. To run the **Codegen** process, you don't have to completely implement the package class: an empty implementation is enough for the app to pick up the module as a proper React Native dependency and to try and generate the scaffolding code.
+
+Create an `android/src/main/java/com/rtncalculator` folder and, inside that folder, create a `CalculatorPackage.java` file.
+
+
+ Java
+
+```java title="CalculatorPackage.java"
+package com.rtncalculator;
+
+import androidx.annotation.Nullable;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.module.model.ReactModuleInfoProvider;
+import com.facebook.react.TurboReactPackage;
+
+import java.util.Collections;
+import java.util.List;
+
+public class CalculatorPackage extends TurboReactPackage {
+
+ @Nullable
+ @Override
+ public NativeModule getModule(String name, ReactApplicationContext reactContext) {
+ return null;
+ }
+
+ @Override
+ public ReactModuleInfoProvider getReactModuleInfoProvider() {
+ return null;
+ }
+}
+```
+
+
+
+ Kotlin
+
+```kotlin title="CalculatorPackage.kt"
+package com.rtncalculator;
+
+import com.facebook.react.TurboReactPackage
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
+import com.facebook.react.module.model.ReactModuleInfoProvider
+
+class CalculatorPackage : TurboReactPackage() {
+ override fun getModule(name: String?, reactContext: ReactApplicationContext): NativeModule? = null
+
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider? = null
+}
+```
+
+
+
+React Native uses the `ReactPackage` interface to understand what native classes the app has to use for the `ViewManager` and `Native Modules` exported by the library.
+
+## 4. Native Code
+
+For the final step in getting your Turbo Native Module ready to go, you'll need to write some native code to connect the JavaScript side to the native platforms. This process requires two main steps:
+
+- Run **Codegen** to see what it generates.
+- Write your native code, implementing the generated interfaces.
+
+When developing a React Native app that uses a Turbo Native Module, it is the responsibility of the app to actually generate the code using **Codegen**. However, when developing a TurboModule as a library, we need to reference the generated code, and it is therefore, useful to see what the app will generate.
+
+As the first step for both iOS and Android, this guide shows how to execute manually the scripts used by **Codegen** to generate the required code. Further information on **Codegen** can be found [here](the-new-architecture/using-codegen).
+
+> [!Warning]
+> The code generated by **Codegen** in this step should not be committed to the versioning system. React Native apps are able to generate the code when the app is built. This allows an app to ensure that all libraries have code generated for the correct version of React Native.
+
+### iOS
+
+#### Generate the code - iOS
+
+To run Codegen for the iOS platform, we need to open a terminal and run the following command:
+
+```sh title="Running Codegen for iOS"
+cd MyApp
+yarn add ../RTNCalculator
+cd ..
+node MyApp/node_modules/react-native/scripts/generate-codegen-artifacts.js \
+ --path MyApp/ \
+ --outputPath RTNCalculator/generated/
+```
+
+This script first adds the `RTNCalculator` module to the app with `yarn add`. Then, it invokes Codegen via the `generate-codegen-artifacts.js` script.
+
+The `--path` option specifies the path to the app, while the `--outputPath` option tells Codegen where to output the generated code.
+
+The output of this process is the following folder structure:
+
+```sh
+generated
+└── build
+ └── generated
+ └── ios
+ ├── FBReactNativeSpec
+ │ ├── FBReactNativeSpec-generated.mm
+ │ └── FBReactNativeSpec.h
+ ├── RCTThirdPartyFabricComponentsProvider.h
+ ├── RCTThirdPartyFabricComponentsProvider.mm
+ ├── RTNCalculatorSpec
+ │ ├── RTNCalculatorSpec-generated.mm
+ │ └── RTNCalculatorSpec.h
+ └── react
+ └── renderer
+ └── components
+ └── rncore
+ ├── ComponentDescriptors.h
+ ├── EventEmitters.cpp
+ ├── EventEmitters.h
+ ├── Props.cpp
+ ├── Props.h
+ ├── RCTComponentViewHelpers.h
+ ├── ShadowNodes.cpp
+ └── ShadowNodes.h
+```
+
+The relevant path for the Turbo Native Module interface is `generated/build/generated/ios/RTNCalculatorSpec`.
+
+See the [Codegen](the-new-architecture/using-codegen) section for further details on the generated files.
+
+> [!Note]
+> When generating the scaffolding code using **Codegen**, iOS does not clean the `build` folder automatically. If you changed the Spec name, for example, and then run **Codegen** again, the old files would be retained.
+> If that happens, remember to remove the `build` folder before running the **Codegen** again.
+>
+> ```
+> cd MyApp/ios
+> rm -rf build
+> ```
+
+#### Write the Native iOS Code
+
+Now add the Native code for your Turbo Native Module. Create two files in the `RTNCalculator/ios` folder:
+
+1. The `RTNCalculator.h`, a header file for the module.
+2. The `RTNCalculator.mm`, the implementation of the module.
+
+##### RTNCalculator.h
+
+```objc title="RTNCalculator.h"
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface RTNCalculator : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
+```
+
+This file defines the interface for the `RTNCalculator` module. Here, we can add any native method we may want to invoke on the view. For this guide, we don't need anything, therefore the interface is empty.
+
+##### RTNCalculator.mm
+
+```objc title="RTNCalculator.mm"
+#import "RTNCalculatorSpec.h"
+#import "RTNCalculator.h"
+
+@implementation RTNCalculator
+
+RCT_EXPORT_MODULE()
+
+- (void)add:(double)a b:(double)b resolve:(RCTPromiseResolveBlock)resolve reject:(RCTPromiseRejectBlock)reject {
+ NSNumber *result = [[NSNumber alloc] initWithInteger:a+b];
+ resolve(result);
+}
+
+- (std::shared_ptr)getTurboModule:
+ (const facebook::react::ObjCTurboModule::InitParams &)params
+{
+ return std::make_shared(params);
+}
+
+@end
+```
+
+The most important call is to the `RCT_EXPORT_MODULE`, which is required to export the module so that React Native can load the Turbo Native Module.
+
+Then the `add` method, whose signature must match the one specified by the Codegen in the `RTNCalculatorSpec.h`.
+
+Finally, the `getTurboModule` method gets an instance of the Turbo Native Module so that the JavaScript side can invoke its methods. The function is defined in (and requested by) the `RTNCalculatorSpec.h` file that was generated earlier by Codegen.
+
+> [!Tip]
+> There are other macros that can be used to export modules and methods. You view the code that specifies them [here](https://github.com/facebook/react-native/blob/main/packages/react-native/React/Base/RCTBridgeModule.h).
+
+### Android
+
+Android follows similar steps to iOS. We have to generate the code for Android, and then we have to write some native code to make it work.
+
+#### Generate the Code - Android
+
+To generate the code for Android, we need to manually invoke Codegen. This is done similarly to what we did for iOS: first, we need to add the package to the app, and then we need to invoke a script.
+
+```sh title="Running Codegen for Android"
+cd MyApp
+yarn add ../RTNCalculator
+cd android
+./gradlew generateCodegenArtifactsFromSchema
+```
+
+This script first adds the package to the app, in the same way iOS does. Then, after moving to the `android` folder, it invokes a Gradle task to create the generated code.
+
+> [!Tip]
+> To run **Codegen**, you need to enable the **New Architecture** in the Android app. This can be done by opening the `gradle.properties` files and by switching the `newArchEnabled` property from `false` to `true`.
+
+The generated code is stored in the `MyApp/node_modules/rtn-calculator/android/build/generated/source/codegen` folder and it has this structure:
+
+```title="Android generated code"
+codegen
+├── java
+│ └── com
+│ └── rtncalculator
+│ └── NativeCalculatorSpec.java
+├── jni
+│ ├── Android.mk
+│ ├── CMakeLists.txt
+│ ├── RTNCalculator-generated.cpp
+│ ├── RTNCalculator.h
+│ └── react
+│ └── renderer
+│ └── components
+│ └── RTNCalculator
+│ ├── ComponentDescriptors.h
+│ ├── EventEmitters.cpp
+│ ├── EventEmitters.h
+│ ├── Props.cpp
+│ ├── Props.h
+│ ├── ShadowNodes.cpp
+│ └── ShadowNodes.h
+└── schema.json
+```
+
+#### Write the Native Android Code
+
+The native code for the Android side of a Turbo Native Module requires:
+
+1. to create a `CalculatorModule.java` that implements the module.
+2. to update the `CalculatorPackage.java` created in the previous step.
+
+The final structure within the Android library should look like this:
+
+```title="Android Folder Structure"
+android
+├── build.gradle
+└── src
+ └── main
+ └── java
+ └── com
+ └── rtncalculator
+ ├── CalculatorModule.java
+ └── CalculatorPackage.java
+```
+
+##### Creating the `CalculatorModule.java`
+
+
+ Java
+
+```java title="CalculatorModule.java"
+package com.rtncalculator;
+
+import androidx.annotation.NonNull;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.Promise;
+import com.facebook.react.bridge.ReactApplicationContext;
+import com.facebook.react.bridge.ReactContext;
+import com.facebook.react.bridge.ReactContextBaseJavaModule;
+import com.facebook.react.bridge.ReactMethod;
+import java.util.Map;
+import java.util.HashMap;
+import com.rtncalculator.NativeCalculatorSpec;
+
+public class CalculatorModule extends NativeCalculatorSpec {
+
+ public static String NAME = "RTNCalculator";
+
+ CalculatorModule(ReactApplicationContext context) {
+ super(context);
+ }
+
+ @Override
+ @NonNull
+ public String getName() {
+ return NAME;
+ }
+
+ @Override
+ public void add(double a, double b, Promise promise) {
+ promise.resolve(a + b);
+ }
+}
+```
+
+
+
+ Kotlin
+
+```kotlin title="CalculatorModule.kt"
+package com.rtncalculator
+
+import com.facebook.react.bridge.Promise
+import com.facebook.react.bridge.ReactApplicationContext
+import com.rtncalculator.NativeCalculatorSpec
+
+class CalculatorModule(reactContext: ReactApplicationContext) : NativeCalculatorSpec(reactContext) {
+
+ override fun getName() = NAME
+
+ override fun add(a: Double, b: Double, promise: Promise) {
+ promise.resolve(a + b)
+ }
+
+ companion object {
+ const val NAME = "RTNCalculator"
+ }
+}
+```
+
+
+
+This class implements the module itself, which extends the `NativeCalculatorSpec` that was generated from the `NativeCalculator` JavaScript specification file.
+
+##### Updating the `CalculatorPackage.java`
+
+
+ Java
+
+```diff title="CalculatorPackage.java"
+package com.rtncalculator;
+
+import androidx.annotation.Nullable;
+import com.facebook.react.bridge.NativeModule;
+import com.facebook.react.bridge.ReactApplicationContext;
++ import com.facebook.react.module.model.ReactModuleInfo;
+import com.facebook.react.module.model.ReactModuleInfoProvider;
+import com.facebook.react.TurboReactPackage;
+
+import java.util.Collections;
+import java.util.List;
++ import java.util.HashMap;
++ import java.util.Map;
+
+public class CalculatorPackage extends TurboReactPackage {
+
+ @Nullable
+ @Override
+ public NativeModule getModule(String name, ReactApplicationContext reactContext) {
++ if (name.equals(CalculatorModule.NAME)) {
++ return new CalculatorModule(reactContext);
++ } else {
+ return null;
++ }
+ }
+
+
+ @Override
+ public ReactModuleInfoProvider getReactModuleInfoProvider() {
+- return null;
++ return () -> {
++ final Map moduleInfos = new HashMap<>();
++ moduleInfos.put(
++ CalculatorModule.NAME,
++ new ReactModuleInfo(
++ CalculatorModule.NAME,
++ CalculatorModule.NAME,
++ false, // canOverrideExistingModule
++ false, // needsEagerInit
++ true, // hasConstants
++ false, // isCxxModule
++ true // isTurboModule
++ ));
++ return moduleInfos;
++ };
+ }
+}
+```
+
+
+
+
+ Kotlin
+
+```diff title="CalculatorPackage.kt"
+package com.rtncalculator;
+
+import com.facebook.react.TurboReactPackage
+import com.facebook.react.bridge.NativeModule
+import com.facebook.react.bridge.ReactApplicationContext
++import com.facebook.react.module.model.ReactModuleInfo
+import com.facebook.react.module.model.ReactModuleInfoProvider
+
+class CalculatorPackage : TurboReactPackage() {
+- override fun getModule(name: String?, reactContext: ReactApplicationContext): NativeModule? = null
++ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? =
++ if (name == CalculatorModule.NAME) {
++ CalculatorModule(reactContext)
++ } else {
++ null
++ }
+
+- override fun getReactModuleInfoProvider() = ReactModuleInfoProvider? = null
++ override fun getReactModuleInfoProvider() = ReactModuleInfoProvider {
++ mapOf(
++ CalculatorModule.NAME to ReactModuleInfo(
++ CalculatorModule.NAME,
++ CalculatorModule.NAME,
++ false, // canOverrideExistingModule
++ false, // needsEagerInit
++ true, // hasConstants
++ false, // isCxxModule
++ true // isTurboModule
++ )
++ )
++ }
+}
+```
+
+
+
+This is the last piece of Native Code for Android. It defines the `TurboReactPackage` object that will be used by the app to load the module.
+
+### Final structure
+
+The final structure should look like this:
+
+```sh
+TurboModulesGuide
+├── MyApp
+└── RTNCalculator
+ ├── android
+ │ ├── build.gradle
+ │ └── src
+ │ └── main
+ │ └── java
+ │ └── com
+ │ └── rtncalculator
+ │ ├── CalculatorPackage.java
+ │ └── CalculatorModule.java
+ ├── generated
+ ├── ios
+ │ ├── RTNCalculator.h
+ │ └── RTNCalculator.mm
+ ├── js
+ │ └── NativeCalculator.ts
+ ├── package.json
+ └── rtn-calculator.podspec
+```
+
+## 5. Adding the Turbo Native Module to your App
+
+Now you can install and use the Turbo Native Module in your app.
+
+### Shared
+
+First of all, we need to add the NPM package which contains the Component to the app. This can be done with the following command:
+
+```sh
+cd MyApp
+yarn add ../RTNCalculator
+```
+
+This command will add the `RTNCalculator` module to the `node_modules` of your app.
+
+### iOS
+
+Then, you need to install the new dependencies in your iOS project. To do so, run these commands:
+
+```sh
+cd ios
+RCT_NEW_ARCH_ENABLED=1 bundle exec pod install
+```
+
+This command will look for all the dependencies of the project and it will install the iOS ones. The `RCT_NEW_ARCH_ENABLED=1` instruct **CocoaPods** that it has to run some additional operations to run **Codegen**.
+
+> [!Note]
+> You may have to run `bundle install` once before you can use `RCT_NEW_ARCH_ENABLED=1 bundle exec pod install`. You won't need to run `bundle install` anymore, unless you need to change the Ruby dependencies.
+
+### Android
+
+Android configuration requires to enable the **New Architecture**:
+
+1. Open the `android/gradle.properties` file
+2. Scroll down to the end of the file and switch the `newArchEnabled` property from `false` to `true`.
+
+### JavaScript
+
+Now you can use your Turbo Native Module calculator in your app!
+
+Here's an example App.js file using the `add` method:
+
+
+ Flow
+
+```typescript title="App.js"
+/**
+ * Sample React Native App
+ * https://github.com/facebook/react-native
+ *
+ * @format
+ * @flow strict-local
+ */
+import React from 'react';
+import {useState} from 'react';
+import type {Node} from 'react';
+import {
+ SafeAreaView,
+ StatusBar,
+ Text,
+ Button,
+} from 'react-native';
+import RTNCalculator from 'rtn-calculator/js/NativeCalculator';
+
+const App: () => Node = () => {
+ const [result, setResult] = useState(null);
+ return (
+
+
+
+ 3+7={result ?? '??'}
+
+ {
+ const value = await RTNCalculator.add(3, 7);
+ setResult(value);
+ }}
+ />
+
+ );
+};
+export default App;
+```
+
+
+
+
+ TypeScript
+
+```typescript title="App.tsx"
+/**
+ * Sample React Native App
+ * https://github.com/facebook/react-native
+ *
+ * @format
+ */
+import React from 'react';
+import {useState} from 'react';
+import {
+ SafeAreaView,
+ StatusBar,
+ Text,
+ Button,
+} from 'react-native';
+import RTNCalculator from 'rtn-calculator/js/NativeCalculator';
+
+const App: () => JSX.Element = () => {
+ const [result, setResult] = useState(null);
+ return (
+
+
+
+ 3+7={result ?? '??'}
+
+ {
+ const value = await RTNCalculator?.add(3, 7);
+ setResult(value ?? null);
+ }}
+ />
+
+ );
+};
+export default App;
+```
+
+
+
+Try this out to see your Turbo Native Module in action!
+
+---
+
+> [!IMPORTANT]
+> This documentation is still experimental and details are subject to changes as we iterate.
+> Feel free to share your feedback on this [discussion](https://github.com/reactwg/react-native-new-architecture/discussions/8).
+>
+> Moreover, it contains **several manual steps**. Please note that this won't be representative of the final developer experience once the New Architecture is stable. We're working on tools, templates and libraries to help you get started fast on the New Architecture, without having to go through the whole setup.
diff --git a/cnwebsite/versioned_docs/version-0.85/nodes.md b/cnwebsite/versioned_docs/version-0.85/nodes.md
new file mode 100644
index 00000000000..47c55a504e8
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/nodes.md
@@ -0,0 +1,18 @@
+---
+id: nodes
+title: 来自 refs 的节点
+---
+
+React Native 应用会渲染一个表示 UI 的原生视图树,类似于 React DOM 在 Web 上的做法(DOM 树)。React Native 通过 [refs](https://react.dev/learn/manipulating-the-dom-with-refs) 提供对这个树的命令式访问,所有原生组件(包括内置组件如 [`View`](/docs/next/view) 渲染的组件)都会返回这些 refs。
+
+React Native 提供 3 种类型的节点:
+
+- [元素节点](/docs/next/element-nodes):元素节点表示原生视图树中的原生组件(类似于 Web 上的 [Element](https://developer.mozilla.org/zh-CN/docs/Web/API/Element) 节点)。它们通过 refs 由所有原生组件提供。
+- [文本节点](/docs/next/text-nodes):文本节点表示树中的原始文本内容(类似于 Web 上的 [`Text`](https://developer.mozilla.org/zh-CN/docs/Web/API/Text) 节点)。它们不能直接通过 `refs` 访问,但可以使用元素 refs 上的方法(如 [`childNodes`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/childNodes))来访问。
+- [文档节点](/docs/next/document-nodes):文档节点表示完整的原生视图树(类似于 Web 上的 [`Document`](https://developer.mozilla.org/zh-CN/docs/Web/API/Document) 节点)。像文本节点一样,它们只能通过其他节点访问,使用如 [`ownerDocument`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/ownerDocument) 这样的属性。
+
+与 Web 上一样,这些节点可用于遍历渲染的 UI 树、访问布局信息或执行命令式操作(如 `focus`)。
+
+:::info
+**与 Web 不同的是,这些节点不允许变更**(例如:[`node.appendChild`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/appendChild)),因为树的内容完全由 React 渲染器管理。
+:::
diff --git a/cnwebsite/versioned_docs/version-0.85/optimizing-flatlist-configuration.md b/cnwebsite/versioned_docs/version-0.85/optimizing-flatlist-configuration.md
new file mode 100644
index 00000000000..d9bbd081d21
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/optimizing-flatlist-configuration.md
@@ -0,0 +1,154 @@
+---
+id: optimizing-flatlist-configuration
+title: 列表配置优化
+---
+
+## 术语定义
+
+- **VirtualizedList:** `FlatList`背后的基础支撑组件(是 React Native 对[`虚拟列表 Virtual List`](https://bvaughn.github.io/react-virtualized/#/components/List)概念的实现)。
+
+- **内存开销 Memory consumption:** 列表在内存中存放多少数据。开销过大可能导致应用崩溃。
+
+- **响应度 Responsiveness:** 应用对于用户操作的响应速度。比如低响应度就是你在操作时,应用要卡一会儿才响应。
+
+- **空白区 Blank areas:** 当`VirtualizedList`渲染的速度跟不上你滑动的速度时,你可能会在列表中看到一些尚未完成渲染的空白占位元素。
+
+- **视口 Viewport:** 已渲染内容的可视区域。
+
+- **滑动窗口 Window:** 内容组件应该被挂载的区域,通常比视口(viewport)大得多。
+
+## Props
+
+下面列出了一些可以提升`FlatList`性能的重要技巧:
+
+### removeClippedSubviews
+
+| 类型 | 默认值 |
+| ------- | ----------------------------------- |
+| Boolean | Android 上为 `true`,否则为 `false` |
+
+如果设为 `true`,那些超出视口范围的视图会从原生视图层级结构中分离。
+
+**好处:** 启用此选项可减少花在主线程上的时间,从而降低丢帧的风险。原理是对视口之外的视图不进行本地渲染和绘图遍历。
+
+**坏处:** 请注意,这种实现可能会有 bug,比如丢失内容(主要是在 iOS 上观察到的),特别是当你使用变换和/或绝对定位做复杂的事情时。另外,请注意这并不会节省大量的内存,因为视图并没有被销毁,只是被分离了。
+
+### maxToRenderPerBatch
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| Number | 10 |
+
+这是一个可以通过 `FlatList` 传递的 `VirtualizedList` 属性。它控制每批渲染的元素数量,也就是每次滚动时渲染的下一组元素。
+
+**好处:** 设置较大的数值意味着在滚动时会减少视觉上的空白区域(提高填充率)。
+
+**坏处:** 每批处理更多元素意味着更长的 JavaScript 执行时间,可能会阻塞其他事件处理,例如按键操作,从而影响响应速度。
+
+### updateCellsBatchingPeriod
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| Number | 50 |
+
+`maxToRenderPerBatch` 告诉 `VirtualizedList` 每批次渲染的元素数量,而 `updateCellsBatchingPeriod` 则用于设置两次批量渲染之间的延迟毫秒数(也就是组件渲染可见区域内元素的频率)。
+
+**好处:** 将这个属性与 `maxToRenderPerBatch` 结合使用,你就可以灵活控制渲染的节奏,比如在频率较低时渲染更多元素,或者在频率较高时渲染较少元素。
+
+**坏处:** 频率过低可能会导致出现空白区域,而频率过高则可能影响组件的响应速度。
+
+### initialNumToRender
+
+| 类型 | Default |
+| ------ | ------- |
+| Number | 10 |
+
+初始渲染的元素数量。
+
+**好处:** 为每个设备定义精确的(刚好可以)覆盖屏幕的项目数量。这可以大大提升初始渲染的性能。
+
+**坏处:** 如果设置的 `initialNumToRender` 值过低,尤其是小到不足以覆盖初始渲染时的可视区域,就可能会出现空白区域。
+
+### windowSize
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| Number | 21 |
+
+这里传递的数字是一个度量单位,其中 1 相当于视口高度。默认值为 21(上方 10 个视口,下方 10 个视口,中间一个视口)。
+
+**好处:** `windowSize` 值越大,滚动时看到空白区域的概率就越小。另一方面,`windowSize` 值越小,同时加载的元素就越少,从而节省内存。
+
+**坏处:** 对于较大的 `windowSize`,内存消耗会更多。对于较小的 `windowSize`,看到空白区域的概率会更大。
+
+## 列表组件的优化要点
+
+接下来是展示列表项组件的一些小技巧。列表项组件是列表的核心,所以它们的性能要足够好。
+
+### 使用简单组件
+
+组件越复杂一般渲染就越慢。
+在列表项中尽量避免过多的逻辑和嵌套。如果你在应用中经常复用这个列表项组件,那就专门为这些大型列表创建一个组件,尽可能减少其中的逻辑和嵌套。
+
+### 使用轻量组件
+
+组件太重自然也会拖慢渲染。尽量避免使用大图片(优先使用裁剪过的版本或是缩略图,总之越小越好)。和负责设计的同事协商,在列表中尽可能简化特效和交互,精简要展示的信息,把长内容移到详情页中。
+
+### 使用`memo()`
+
+`React.memo()` 会创建一个带有记忆化功能的组件,只有当传递给组件的 props 发生变化时,该组件才会重新渲染。我们可以利用这个函数来优化 FlatList 中的组件。
+
+```tsx
+import React, {memo} from 'react';
+import {View, Text} from 'react-native';
+
+const MyListItem = memo(
+ ({title}: {title: string}) => (
+
+ {title}
+
+ ),
+ (prevProps, nextProps) => {
+ return prevProps.title === nextProps.title;
+ },
+);
+
+export default MyListItem;
+```
+
+在这个例子中,我们决定只有在标题发生变化时才重新渲染`MyListItem`组件。我们将比较函数作为第二个参数传递给`React.memo()`,以便只在指定的属性发生变化时才重新渲染组件。如果比较函数返回`true`,则组件将不会被重新渲染。
+
+### 使用优化缓存的图片库
+
+你可以使用社区的扩展包(例如来自 [Dream11](https://github.com/ds-horizon) 的 [@d11/react-native-fast-image](https://github.com/ds-horizon/react-native-fast-image) )来获得更高性能的图片加载体验。列表中的每张图片都是一个`new Image()`实例。它触发 loaded 钩子的速度越快,你的 Javascript 线程就能越快再次空闲下来。
+
+### 使用 getItemLayout
+
+如果您的列表项组件都具有相同的高度(或宽度,对于水平列表),则提供 [getItemLayout](flatlist#getitemlayout)属性可以消除您的 `FlatList` 管理异步布局计算的需要。这是一种非常理想的优化技术。
+
+如果您的组件具有动态大小并且确实需要性能,请考虑询问设计团队是否可以重新设计以获得更好的性能。
+
+### 使用 keyExtractor 或 key
+
+你可以为 `FlatList` 组件设置 [`keyExtractor`](flatlist#keyextractor) 属性。这个属性用于缓存,同时作为 React 的 `key` 来跟踪列表项的重新排序。
+你也可以在列表项组件中使用 `key` 属性。
+
+### 避免在 renderItem 中使用匿名函数
+
+对于函数式组件,把 `renderItem` 函数移到返回的 JSX 之外。另外,确保把它包裹在 `useCallback` 钩子里,防止每次渲染时都重新创建。
+对于类组件,把 `renderItem` 函数移到 render 函数之外,这样每次调用`render`函数时它就不会重新创建自己了。
+
+```tsx
+const renderItem = useCallback(({item}) => (
+
+ {item.title}
+
+ ), []);
+
+return (
+ // ...
+
+ ;
+ // ...
+);
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/optimizing-javascript-loading.md b/cnwebsite/versioned_docs/version-0.85/optimizing-javascript-loading.md
new file mode 100644
index 00000000000..0a0a29431f1
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/optimizing-javascript-loading.md
@@ -0,0 +1,217 @@
+---
+id: optimizing-javascript-loading
+title: 优化 JavaScript 加载
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+解析和运行 JavaScript 代码需要内存和时间。因此,随着你的应用程序增长,通常将代码加载延迟到首次需要时是有用的。React Native 自带一些默认开启的标准优化,并且你可以在自己的代码中采用一些技术来帮助 React 更有效地加载你的应用程序。还有一些适合非常大应用程序的高级自动优化(它们也有自己的权衡)。
+
+## 推荐:使用 Hermes
+
+[Hermes](./hermes) 是新 React Native 应用的默认引擎,它对高效代码加载进行了高度优化。在发布版本中,JavaScript 代码会完全提前编译成字节码。字节码按需加载到内存中,并不需要像普通 JavaScript 那样进行解析。
+
+## 推荐:延迟加载大型组件
+
+如果一个包含大量代码/依赖项的组件在最初渲染应用程序时不太可能被使用,您可以使用 React 的 [`lazy`](https://react.dev/reference/react/lazy) API 来推迟加载其代码,直到它首次呈现。通常,您应该考虑延迟加载应用程序中的屏幕级组件,这样添加新屏幕到您的应用程序就不会增加其启动时间。
+
+:::info
+阅读更多关于 [带有 Suspense 的延迟加载组件](https://react.dev/reference/react/lazy#suspense-for-code-splitting) 的信息,包括代码示例,在 React 文档中。
+:::
+
+### 小贴士:避免模块副作用
+
+如果组件模块(或其依赖项)具有*副作用*,例如修改全局变量或在组件外部订阅事件,则延迟加载组件可能会改变应用程序的行为。React 应用中的大多数模块都不应有任何副作用。
+
+```tsx title="SideEffects.tsx"
+import Logger from './utils/Logger';
+
+// 🚩 🚩 🚩 副作用!这必须在 React 开始渲染 SplashScreen 组件之前执行,
+// 如果你决定延迟加载 SplashScreen,它可能会意外地破坏应用中其他地方的代码。(比如需要依赖logger的代码)
+global.logger = new Logger();
+
+export function SplashScreen() {
+ // ...
+}
+```
+
+## 高级:内联调用 `require`
+
+有时,您可能希望将一些代码的加载推迟到第一次使用时,而不是使用 `lazy` 或异步的 `import()`。您可以通过在文件顶部本来会静态使用 `import` 的地方,改用 [`require()`](https://metrobundler.dev/docs/module-api/#require) 函数来实现这一点。
+
+```tsx title="VeryExpensive.tsx"
+import {Component} from 'react';
+import {Text} from 'react-native';
+// ... import 一些开销非常大的模块
+
+export default function VeryExpensive() {
+ // ... 开销非常大的渲染逻辑
+ return Very Expensive Component ;
+}
+```
+
+```tsx title="Optimized.tsx"
+import {useCallback, useState} from 'react';
+import {TouchableOpacity, View, Text} from 'react-native';
+// 一般我们会静态导入某个组件
+// import VeryExpensive from './VeryExpensive';
+// 但由于这个组件开销非常大,这里我们可以改用 require
+
+let VeryExpensive = null;
+
+export default function Optimize() {
+ const [needsExpensive, setNeedsExpensive] = useState(false);
+ const didPress = useCallback(() => {
+ if (VeryExpensive == null) {
+ VeryExpensive = require('./VeryExpensive').default;
+ }
+
+ setNeedsExpensive(true);
+ }, []);
+
+ return (
+
+
+ Load
+
+ {needsExpensive ? : null}
+
+ );
+}
+```
+
+## 高级:自动内联 `require` 调用
+
+如果您使用 React Native CLI 构建您的应用程序,`require` 调用(但不是 `import`)将会自动为您内联,这既适用于您的代码,也适用于您使用的任何第三方包(`node_modules`)。
+
+```tsx
+import {useCallback, useState} from 'react';
+import {TouchableOpacity, View, Text} from 'react-native';
+
+// This top-level require call will be evaluated lazily as part of the component below.
+const VeryExpensive = require('./VeryExpensive').default;
+
+export default function Optimize() {
+ const [needsExpensive, setNeedsExpensive] = useState(false);
+ const didPress = useCallback(() => {
+ setNeedsExpensive(true);
+ }, []);
+
+ return (
+
+
+ Load
+
+ {needsExpensive ? : null}
+
+ );
+}
+```
+
+:::info
+一些 React Native 框架禁用了这种行为。例如在 Expo 项目中,默认情况下不会内联 `require` 调用。你可以通过编辑项目的 Metro 配置,并在 [`getTransformOptions`](https://metrobundler.dev/docs/configuration#gettransformoptions) 中设置 `inlineRequires: true` 来启用此优化。
+:::
+
+### 内联 `require` 的缺陷
+
+内联 `require` 调用会改变模块的评估顺序,甚至可能导致某些模块 _永远不被评估_。这通常可以安全地自动进行,因为 JavaScript 模块通常被编写为无副作用。
+
+如果你的一个模块确实有副作用 - 例如它初始化了某种日志记录机制,或者修补了需要在其他地方调用的全局 API - 那么你可能看到意外的行为甚至崩溃。在这些情况下,你可能想要从这种优化中排除某些模块或完全禁用它。
+
+要 **禁用所有自动内联 `require` 调用:**
+
+更新你的 `metro.config.js` 文件以将 `inlineRequires` transformer 选项设置为 `false`:
+
+```tsx title="metro.config.js"
+module.exports = {
+ transformer: {
+ async getTransformOptions() {
+ return {
+ transform: {
+ inlineRequires: false,
+ },
+ };
+ },
+ },
+};
+```
+
+仅将**某些模块从 `require` 内联中排除**:
+
+有两个相关的转换器选项:`inlineRequires.blockList` 和 `nonInlinedRequires`。请参见代码片段,了解如何使用每个选项的示例。
+
+```tsx title="metro.config.js"
+module.exports = {
+ transformer: {
+ async getTransformOptions() {
+ return {
+ transform: {
+ inlineRequires: {
+ blockList: {
+ // 在 `DoNotInlineHere.js` 中的 require() 调用将不会被内联。
+ [require.resolve('./src/DoNotInlineHere.js')]: true,
+
+ // 其他地方的 require() 调用将被内联,除非它们
+ // 与 nonInlinedRequires 中的任何条目匹配(见下文)。
+ },
+ },
+ nonInlinedRequires: [
+ // 在任何地方的 require('react') 调用都不会被内联
+ 'react',
+ ],
+ },
+ };
+ },
+ },
+};
+```
+
+查看 Metro 文档中的 [`getTransformOptions`](https://metrobundler.dev/docs/configuration#gettransformoptions) 以获取有关设置和微调内联 `require` 的更多详细信息。
+
+## 高级:使用随机访问模块包(非 Hermes)
+
+:::info
+**当 [使用 Hermes](#use-hermes) 时不支持。** Hermes 字节码与 RAM 捆绑包格式不兼容,并且在所有用例中都提供了相同(或更好)的性能。
+:::
+
+随机访问模块捆绑包(也称为 RAM bundle)与上述技术一起工作,以限制需要解析并加载到内存中的 JavaScript 代码量。每个模块都被存储为单独的字符串(或文件),只有在需要执行该模块时才进行解析。
+
+RAM bundle 可以物理分割成单独的文件,或者它们可以使用 _索引_ 格式,由单个文件中的多个模块查找表组成。
+
+
+
+
+在 Android 上,通过编辑 `android/app/build.gradle` 文件来启用 RAM 格式。在行 `apply from: "../../node_modules/react-native/react.gradle"` 之前添加或修改 `project.ext.react` 块:
+
+```groovy
+project.ext.react = [
+ bundleCommand: "ram-bundle",
+]
+```
+
+如果你想在 Android 上使用单个索引文件,请使用以下行:
+
+```
+project.ext.react = [
+ bundleCommand: "ram-bundle",
+ extraPackagerArgs: ["--indexed-ram-bundle"]
+]
+```
+
+
+
+
+在 iOS 上,RAM 包总是被索引(=单个文件)。
+
+通过编辑构建阶段 "Bundle React Native code and images" 来在 Xcode 中启用 RAM 格式。在 `../node_modules/react-native/scripts/react-native-xcode.sh` 前面加上 `export BUNDLE_COMMAND="ram-bundle"`:
+
+```
+export BUNDLE_COMMAND="ram-bundle"
+export NODE_BINARY=node
+../node_modules/react-native/scripts/react-native-xcode.sh
+```
+
+
+
+
+查看 Metro 文档中的 [`getTransformOptions`](https://metrobundler.dev/docs/configuration#gettransformoptions) 以获取有关设置和微调您的 RAM bundle 构建的更多详细信息。
diff --git a/cnwebsite/versioned_docs/version-0.85/other-debugging-methods.md b/cnwebsite/versioned_docs/version-0.85/other-debugging-methods.md
new file mode 100644
index 00000000000..e8f187c5b58
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/other-debugging-methods.md
@@ -0,0 +1,36 @@
+---
+id: other-debugging-methods
+title: 其他调试方法
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+此页面介绍了传统的 JavaScript 调试方法。如果你正在使用新创建的 React Native 或 Expo 应用,我们建议使用 [React Native DevTools](./react-native-devtools)。
+
+## Safari 开发者工具(直接调试 JSC)
+
+当你的应用使用 [JavaScriptCore](https://trac.webkit.org/wiki/JavaScriptCore)(JSC)作为运行时环境时,可以使用 Safari 来调试应用的 iOS 版本。
+
+1. **仅适用于物理设备**:打开"设置"应用,导航到 Safari > 高级,确保"Web 检查器"已打开。
+2. 在 Mac 上,打开 Safari 并启用"开发"菜单。可以在 Safari > 设置... 下找到,然后选择"高级"选项卡,再勾选"显示面向 Web 开发者的功能"。
+3. 在"开发"菜单下找到你的设备,并从子菜单中选择"JSContext"项。这将打开 Safari 的 Web 检查器,其中包括类似于 Chrome 开发者工具的控制台和源代码面板。
+
+
+
+:::tip
+虽然默认情况下可能没有启用 Source Map,但你可以参考[这篇指南](https://blog.nparashuram.com/2019/10/debugging-react-native-ios-apps-with.html)或者[视频](https://www.youtube.com/watch?v=GrGqIIz51k4),了解如何启用它们,并在源代码的正确位置设置断点。
+:::
+
+:::tip
+每次应用重新加载时,都会创建一个新的 JSContext。勾选"Automatically Show Web Inspectors for JSContexts"可以省去你手动选择最新 JSContext 的麻烦。
+:::
+
+## 远程 JavaScript 调试(已移除)
+
+:::warning 重要
+远程 JavaScript 调试功能已在 React Native 0.79 版本中移除。请查看原始的[弃用公告](https://github.com/react-native-community/discussions-and-proposals/discussions/734)。
+
+如果你使用的是较旧版本的 React Native,请查阅[对应版本的文档](/versions)。
+:::
+
+
diff --git a/cnwebsite/versioned_docs/version-0.85/out-of-tree-platforms.md b/cnwebsite/versioned_docs/version-0.85/out-of-tree-platforms.md
new file mode 100644
index 00000000000..5741ee682b7
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/out-of-tree-platforms.md
@@ -0,0 +1,43 @@
+---
+id: out-of-tree-platforms
+title: 多平台支持
+---
+
+React Native不仅适用于 Android 和 iOS - 还有社区支持的项目将其应用于其他平台,例如:
+
+- [React Native Windows](https://github.com/Microsoft/react-native-windows) - React Native 支持 Microsoft Universal Windows Platform (UWP) 和 Windows Presentation Foundation (WPF)
+- [React Native DOM](https://github.com/vincentriemer/react-native-dom) - 一个实验性的、全面的 React Native 到 web 的端口。(不要与[React Native Web](https://github.com/necolas/react-native-web)混淆,两者目标不同)
+- [React Native Desktop](https://github.com/status-im/react-native-desktop) - 一个旨在通过 Qt 的 QML 将 React Native 带到桌面的项目。[React Native Ubuntu](https://github.com/CanonicalLtd/react-native/)的一个分支,已不再维护。
+- [React Native macOS](https://github.com/ptmt/react-native-macos) - 针对 macOS 和 Cocoa 的实验性 React Native 分支
+- [React Native tvOS](https://github.com/react-native-community/react-native-tvos) - 为 Apple tvOS 适配 React Native
+- [alita](https://github.com/areslabs/alita) - 一个实验性的、综合性的 React Native 到微信小程序的端口
+- [Proton Native](https://github.com/kusti8/proton-native) - React Native 的封装器,使用 Qt 面向 Linux、MacOS 和 Windows
+
+## 创建你自己的 React Native 平台
+
+目前,从头开始创建 React Native 平台的过程并没有很好的记录——即将到来的全新架构([Fabric](https://facebook.github.io/react-native/blog/2018/06/14/state-of-react-native-2018))的目标之一是使平台的维护更容易。
+
+### 打包
+
+从 React Native 0.57 开始,你现在可以使用 React Native 的 JavaScript 打包器[Metro](https://facebook.github.io/metro/)注册你的 React Native 平台。这意味着你可以将`--platform example`传递给`npx react-native bundle`,它会查找带有`.example.js`后缀的 JavaScript 文件。
+
+要将你的平台注册到 RNPM,模块名称必须与以下模式之一匹配:
+
+- `react-native-example` - 它会搜索所有以`react-native-`开头的顶级模块
+- `@org/react-native-example` - 它会在所有范围内搜索以`react-native-`开头的模块
+- `@react-native-example/module` - 它会在名称以`@react-native-`开头的范围内搜索所有模块
+
+你还必须在`package.json`中设置一些内容,如下所示:
+
+```json
+{
+ "rnpm": {
+ "haste": {
+ "providesModuleNodeModules": ["react-native-example"],
+ "platforms": ["example"]
+ }
+ }
+}
+```
+
+`"providesModuleNodeModules"`是一组将被添加到 Haste 模块搜索路径的模块,`"platforms"`则是一组将作为有效平台添加的平台后缀。
diff --git a/cnwebsite/versioned_docs/version-0.85/panresponder.md b/cnwebsite/versioned_docs/version-0.85/panresponder.md
new file mode 100644
index 00000000000..89a82c4f757
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/panresponder.md
@@ -0,0 +1,183 @@
+---
+id: panresponder
+title: PanResponder
+---
+
+`PanResponder`类可以将多点触摸操作协调成一个手势。它使得一个单点触摸可以接受更多的触摸操作,也可以用于识别简单的多点触摸手势。
+
+默认情况下`PanResponder`会通过`InteractionManager`来阻止长时间运行的 JS 事件打断当前的手势活动。
+
+它提供了一个对[触摸响应系统](gesture-responder-system.md)响应器的可预测的包装。对于每一个处理函数,它在原生事件之外提供了一个新的`gestureState`对象:
+
+```
+onPanResponderMove: (event, gestureState) => {}
+```
+
+原生事件是指由以下字段组成的合成触摸事件:
+
+- `nativeEvent`
+ - `changedTouches` - 在上一次事件之后,所有发生变化的触摸事件的数组集合(即上一次事件后,所有移动过的触摸点)
+ - `identifier` - 触摸点的 ID
+ - `locationX` - 触摸点相对于父元素的横坐标
+ - `locationY` - 触摸点相对于父元素的纵坐标
+ - `pageX` - 触摸点相对于根元素的横坐标
+ - `pageY` - 触摸点相对于根元素的纵坐标
+ - `target` - 触摸点所在的元素 ID
+ - `timestamp` - 触摸事件的时间戳,可用于移动速度的计算
+ - `touches` - 当前屏幕上的所有触摸点的集合
+
+一个`gestureState`对象有如下的字段:
+
+- `stateID` - 触摸状态的 ID。在屏幕上有至少一个触摸点的情况下,这个 ID 会一直有效。
+- `moveX` - 最近一次移动时的屏幕横坐标
+- `moveY` - 最近一次移动时的屏幕纵坐标
+- `x0` - 当响应器产生时的屏幕坐标
+- `y0` - 当响应器产生时的屏幕坐标
+- `dx` - 从触摸操作开始时的累计横向路程
+- `dy` - 从触摸操作开始时的累计纵向路程
+- `vx` - 当前的横向移动速度
+- `vy` - 当前的纵向移动速度
+- `numberActiveTouches` - 当前在屏幕上的有效触摸点的数量
+
+### 基本用法
+
+```jsx
+const ExampleComponent = () => {
+ const panResponder = React.useRef(
+ PanResponder.create({
+ // 要求成为响应者:
+ onStartShouldSetPanResponder: (evt, gestureState) => true,
+ onStartShouldSetPanResponderCapture: (evt, gestureState) =>
+ true,
+ onMoveShouldSetPanResponder: (evt, gestureState) => true,
+ onMoveShouldSetPanResponderCapture: (evt, gestureState) =>
+ true,
+
+ onPanResponderGrant: (evt, gestureState) => {
+ // 开始手势操作。给用户一些视觉反馈,让他们知道发生了什么事情!
+ // gestureState.d{x,y} 现在会被设置为0
+ },
+ onPanResponderMove: (evt, gestureState) => {
+ // 最近一次的移动距离为gestureState.move{X,Y}
+ // 从成为响应者开始时的累计手势移动距离为gestureState.d{x,y}
+ },
+ onPanResponderTerminationRequest: (evt, gestureState) =>
+ true,
+ onPanResponderRelease: (evt, gestureState) => {
+ // 用户放开了所有的触摸点,且此时视图已经成为了响应者。
+ // 一般来说这意味着一个手势操作已经成功完成。
+ },
+ onPanResponderTerminate: (evt, gestureState) => {
+ // 另一个组件已经成为了新的响应者,所以当前手势将被取消。
+ },
+ onShouldBlockNativeResponder: (evt, gestureState) => {
+ // 返回一个布尔值,决定当前组件是否应该阻止原生组件成为JS响应者
+ // 默认返回true。目前暂时只支持android。
+ return true;
+ },
+ }),
+ ).current;
+
+ return ;
+};
+```
+
+## 示例
+
+`PanResponder` works with `Animated` API to help build complex gestures in the UI. The following example contains an animated `View` component which can be dragged freely across the screen
+
+```SnackPlayer name=PanResponder
+import React, {useRef} from 'react';
+import {Animated, View, StyleSheet, PanResponder, Text} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+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}]),
+ onPanResponderRelease: () => {
+ pan.extractOffset();
+ },
+ }),
+ ).current;
+
+ return (
+
+
+ Drag this box!
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ titleText: {
+ fontSize: 14,
+ lineHeight: 24,
+ fontWeight: 'bold',
+ },
+ box: {
+ height: 150,
+ width: 150,
+ backgroundColor: 'blue',
+ borderRadius: 5,
+ },
+});
+
+export default App;
+```
+
+还可以看看[RNTester 中的 PanResponder 示例](https://github.com/facebook/react-native/blob/main/packages/rn-tester/js/examples/PanResponder/PanResponderExample.js)。
+
+---
+
+# 文档
+
+## 方法
+
+### `create()`
+
+```tsx
+static create(config: PanResponderCallbacks): PanResponderInstance;
+```
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------- | ---- | ------ |
+| config 必需
| 对象 | 见下文 |
+
+`config`对象提供了所有响应器回调的加强版本,不仅仅包括原本的`ResponderSyntheticEvent`,还包括`PanResponder`手势状态的回调。你只要简单的把`onResponder*`回调中的`Responder`替换为`PanResponder`。举例来说,这个`config`对象可能看起来像这样:
+
+- `onMoveShouldSetPanResponder: (e, gestureState) => {...}`
+- `onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}`
+- `onStartShouldSetPanResponder: (e, gestureState) => {...}`
+- `onStartShouldSetPanResponderCapture: (e, gestureState) => {...}`
+- `onPanResponderReject: (e, gestureState) => {...}`
+- `onPanResponderGrant: (e, gestureState) => {...}`
+- `onPanResponderStart: (e, gestureState) => {...}`
+- `onPanResponderEnd: (e, gestureState) => {...}`
+- `onPanResponderRelease: (e, gestureState) => {...}`
+- `onPanResponderMove: (e, gestureState) => {...}`
+- `onPanResponderTerminate: (e, gestureState) => {...}`
+- `onPanResponderTerminationRequest: (e, gestureState) => {...}`
+- `onShouldBlockNativeResponder: (e, gestureState) => {...}`
+
+通常来说,对那些有对应捕获事件的事件来说,我们在捕获阶段更新`gestureState`一次,然后在冒泡阶段直接使用即可。
+
+注意 `onStartShould\*` 回调。他们只会在此节点冒泡/捕获的开始/结束事件中提供已经更新过的`gestureState`。一旦这个节点成为了事件的响应者,则所有的开始/结束事件都会被手势正确处理,并且`gestureState`也会被正确更新。(numberActiveTouches)有可能没有包含所有的触摸点,除非你就是触摸事件的响应者。
diff --git a/cnwebsite/versioned_docs/version-0.85/performance.md b/cnwebsite/versioned_docs/version-0.85/performance.md
new file mode 100644
index 00000000000..3c444773291
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/performance.md
@@ -0,0 +1,97 @@
+---
+id: performance
+title: 性能综述
+---
+
+使用 React Native 替代基于 WebView 的框架来开发 App 的一个强有力的理由,就是为了使 App 可以达到每秒 60 帧(足够流畅),并且能有类似原生 App 的外观和手感。因此我们也尽可能地优化 React Native 去实现这一目标,使开发者能集中精力处理 App 的业务逻辑,而不用费心考虑性能。但是,总还是有一些地方有所欠缺,以及在某些场合 React Native 还不能够替你决定如何进行优化(用原生代码写也无法避免),因此人工的干预依然是必要的。
+
+本文的目的是教给你一些基本的知识,来帮你排查性能方面的问题,以及探讨这些问题产生的原因和推荐的解决方法。
+
+## 关于“帧”你所需要知道的
+
+老一辈人常常把电影称为“移动的画”,是因为视频中逼真的动态效果其实是一种幻觉,这种幻觉是由一组静态的图片以一个稳定的速度快速变化所产生的。我们把这组图片中的每一张图片叫做一帧,而每秒钟显示的帧数直接的影响了视频(或者说用户界面)的流畅度和真实感。iOS 设备提供了每秒 60 的帧率,这就留给了开发者和 UI 系统大约 16.67ms 来完成生成一张静态图片(帧)所需要的所有工作。如果在这分派的 16.67ms 之内没有能够完成这些工作,就会引发‘丢帧’的后果,使界面表现的不够流畅。
+
+下面要讲的事情可能更为复杂:请先调出你应用的开发菜单,打开`Show FPS Monitor`. 你会注意到有两个不同的帧率.
+
+
+
+### JS 帧率(JavaScript 线程)
+
+对大多数 React Native 应用来说,业务逻辑是运行在 JavaScript 线程上的。这是 React 应用所在的线程,也是发生 API 调用,以及处理触摸事件等操作的线程。更新数据到原生支持的视图是批量进行的,并且在事件循环每进行一次的时候被发送到原生端,这一步通常会在一帧时间结束之前处理完(如果一切顺利的话)。如果 JavaScript 线程有一帧没有及时响应,就被认为发生了一次丢帧。 例如,你在一个复杂应用的根组件上调用了`this.setState`,从而导致一次开销很大的子组件树的重绘,可想而知,这可能会花费 200ms 也就是整整 12 帧的丢失。此时,任何由 JavaScript 控制的动画都会卡住。只要卡顿超过 100ms,用户就会明显的感觉到。
+
+这种情况经常发生在老的`Navigator`导航器的切换过程中:当你 push 一个新的路由时,JavaScript 需要绘制新场景所需的所有组件,以发送正确的命令给原生端去创建视图。由于切换是由 JavaScript 线程所控制,因此经常会占用若干帧的时间,引起一些卡顿。有的时候,组件会在`componentDidMount`函数中做一些额外的事情,这甚至可能会导致页面切换过程中多达一秒的卡顿。
+
+另一个例子是老的触摸事件的响应:如果你正在 JavaScript 线程处理一个跨越多个帧的工作,你可能会注意到`TouchableOpacity`的响应被延迟了。这是因为 JavaScript 线程太忙了,不能够处理主线程发送过来的原始触摸事件,结果`TouchableOpacity`就不能及时响应这些事件并命令主线程的页面去调整透明度了。
+
+### UI 帧率(主线程)
+
+很多人会注意到,`NavigatorIOS`的性能要比老的纯 JS 实现的`Navigator`好的多。原因就是它的切换动画是完全在主线程上执行的,因此不会被 JavaScript 线程上的掉帧所影响。
+
+同样,当 JavaScript 线程卡住的时候,你仍然可以欢快的上下滚动`ScrollView`,因为`ScrollView`运行在主线程之上(尽管滚动事件会被分发到 JS 线程,但是接收这些事件对于滚动这个动作来说并不必要)。
+
+## 性能问题的常见原因
+
+### 开发模式 (`dev=true`)
+
+JavaScript 线程的性能在开发模式下是很糟糕的。这是不可避免的,因为有许多工作需要在运行的时候去做,譬如使你获得良好的警告和错误信息,又比如验证属性类型(propTypes)以及产生各种其他的警告。请务必注意在[release 模式](running-on-device.md#发布应用)下去测试性能。
+
+### console.log 语句
+
+在运行打好了离线包的应用时,控制台大量打印语句可能会拖累 JavaScript 线程。注意有些第三方调试库也可能包含控制台打印语句,比如[redux-logger](https://github.com/evgenyrodionov/redux-logger),所以在发布应用前请务必仔细检查,确保全部移除。
+
+> 有个[babel 插件](https://babeljs.io/docs/plugins/transform-remove-console/)可以帮你移除所有的`console.*`调用。首先需要使用`yarn add --dev babel-plugin-transform-remove-console`来安装,然后在项目根目录下编辑(或者是新建)一个名为·.babelrc`的文件,在其中加入:
+
+```json
+{
+ "env": {
+ "production": {
+ "plugins": ["transform-remove-console"]
+ }
+ }
+}
+```
+
+这样在打包发布时,所有的控制台语句就会被自动移除,而在调试时它们仍然会被正常调用。
+
+### `ListView` 首次渲染缓慢或者由于列表很大导致滑动很慢
+
+用新的[`FlatList`](flatlist)或者[`SectionList`](sectionlist)组件替代。除了简化了API,这些新的列表组件在性能方面都有了极大的提升, 其中最主要的一个是无论列表有多少行,它的内存使用都是常数级的。
+
+如果你的[`FlatList`](flatlist)渲染得很慢, 请确保你使用了[`getItemLayout`](flatlist.md#getitemlayout),它通过跳过对items的处理来优化你的渲染速度。
+
+### 在重绘一个几乎没有什么变化的页面时,JS 帧率严重降低
+
+你可以实现`shouldComponentUpdate`函数来指明在什么样的确切条件下,你希望这个组件得到重绘。如果你编写的是纯粹的组件(界面完全由 props 和 state 所决定),你可以利用`PureComponent`来为你做这个工作。再强调一次,不可变的数据结构(immutable,即对于引用类型数据,不修改原值,而是复制后修改并返回新值)在提速方面非常有用 —— 当你不得不对一个长列表对象做一个深度的比较,它会使重绘你的整个组件更加快速,而且代码量更少。
+
+### Dropping JS thread FPS because of doing a lot of work on the JavaScript thread at the same time
+
+"Slow Navigator transitions" is the most common manifestation of this, but there are other times this can happen. Using InteractionManager can be a good approach, but if the user experience cost is too high to delay work during an animation, then you might want to consider LayoutAnimation.
+
+The Animated API currently calculates each keyframe on-demand on the JavaScript thread unless you [set `useNativeDriver: true`](https://reactnative.dev/blog/2017/02/14/using-native-driver-for-animated), while LayoutAnimation leverages Core Animation and is unaffected by JS thread and main thread frame drops.
+
+One case where I have used this is for animating in a modal (sliding down from top and fading in a translucent overlay) while initializing and perhaps receiving responses for several network requests, rendering the contents of the modal, and updating the view where the modal was opened from. See the Animations guide for more information about how to use LayoutAnimation.
+
+Caveats:
+
+- LayoutAnimation only works for fire-and-forget animations ("static" animations) -- if it must be interruptible, you will need to use `Animated`.
+
+### 在屏幕上移动视图(滚动,切换,旋转)时,UI 线程掉帧
+
+当具有透明背景的文本位于一张图片上时,或者在每帧重绘视图时需要用到透明合成的任何其他情况下,这种现象尤为明显。设置`shouldRasterizeIOS`或者`renderToHardwareTextureAndroid`属性可以显著改善这一现象。
+注意不要过度使用该特性,否则你的内存使用量将会飞涨。在使用时,要评估你的性能和内存使用情况。如果你没有需要移动这个视图的需求,请关闭这一属性。
+
+### 使用动画改变图片的尺寸时,UI 线程掉帧
+
+在 iOS 上,每次调整 Image 组件的宽度或者高度,都需要重新裁剪和缩放原始图片。这个操作开销会非常大,尤其是大的图片。比起直接修改尺寸,更好的方案是使用`transform: [{scale}]`的样式属性来改变尺寸。比如当你点击一个图片,要将它放大到全屏的时候,就可以使用这个属性。
+
+### Touchable 系列组件不能很好的响应
+
+有些时候,如果我们有一项操作与点击事件所带来的透明度改变或者高亮效果发生在同一帧中,那么有可能在`onPress`函数结束之前我们都看不到这些效果。比如在`onPress`执行了一个`setState`的操作,这个操作需要大量计算工作并且导致了掉帧。对此的一个解决方案是将`onPress`处理函数中的操作封装到`requestAnimationFrame`中:
+
+```jsx
+handleOnPress() {
+ requestAnimationFrame(() => {
+ this.doExpensiveAction();
+ });
+}
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/permissionsandroid.md b/cnwebsite/versioned_docs/version-0.85/permissionsandroid.md
new file mode 100644
index 00000000000..6eb958ef2c5
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/permissionsandroid.md
@@ -0,0 +1,205 @@
+---
+id: permissionsandroid
+title: PermissionsAndroid
+---
+
+
+
仅适用于有 Native 代码的项目
+
以下部分仅适用于包含原生代码的项目。如果你正在使用 Expo 管理工作流,请参阅 Expo 文档中的权限指南 以获取合适的替代方案。
+
+
+`PermissionsAndroid` 可以访问 Android M(也就是 6.0)开始提供的权限模型。有一些权限写在`AndroidManifest.xml`就可以在安装时自动获得,但有一些“危险”的权限则需要弹出提示框供用户选择。本 API 即用于后一种情形。
+
+在低于 Android 6.0 的设备上,权限只要写在`AndroidManifest.xml`里就会自动获得,此情形下`check`会始终返回`true`和而`request`方法将始终解析为`PermissionsAndroid.RESULTS.GRANTED`。
+
+如果用户之前拒绝过你的某项权限请求,那么系统会建议你显示一个为什么需要这个权限的“详细解释”(`rationale`参数)。如果用户之前拒绝过,那么当你再次申请的时候,弹出的就可能不是原先的申请信息,而是`rationale`参数里提供的进一步解释。
+
+### 示例
+
+```SnackPlayer name=PermissionsAndroid%20Example&supportedPlatforms=android
+import React from 'react';
+import {
+ Button,
+ PermissionsAndroid,
+ StatusBar,
+ StyleSheet,
+ Text,
+} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const requestCameraPermission = async () => {
+ try {
+ const granted = await PermissionsAndroid.request(
+ PermissionsAndroid.PERMISSIONS.CAMERA,
+ {
+ 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',
+ },
+ );
+ if (granted === PermissionsAndroid.RESULTS.GRANTED) {
+ console.log('You can use the camera');
+ } else {
+ console.log('Camera permission denied');
+ }
+ } catch (err) {
+ console.warn(err);
+ }
+};
+
+const App = () => (
+
+
+ Try permissions
+
+
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ paddingTop: StatusBar.currentHeight,
+ backgroundColor: '#ecf0f1',
+ padding: 8,
+ },
+ item: {
+ margin: 24,
+ fontSize: 18,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ },
+});
+
+export default App;
+```
+
+### 需要提示用户的权限列表
+
+需要提示用户的权限都以常量形式列在`PermissionsAndroid.PERMISSIONS`中:
+
+- `READ_CALENDAR`: 'android.permission.READ_CALENDAR'
+- `WRITE_CALENDAR`: 'android.permission.WRITE_CALENDAR'
+- `CAMERA`: 'android.permission.CAMERA'
+- `READ_CONTACTS`: 'android.permission.READ_CONTACTS'
+- `WRITE_CONTACTS`: 'android.permission.WRITE_CONTACTS'
+- `GET_ACCOUNTS`: 'android.permission.GET_ACCOUNTS'
+- `ACCESS_FINE_LOCATION`: 'android.permission.ACCESS_FINE_LOCATION'
+- `ACCESS_COARSE_LOCATION`: 'android.permission.ACCESS_COARSE_LOCATION'
+- `ACCESS_BACKGROUND_LOCATION`: 'android.permission.ACCESS_BACKGROUND_LOCATION'
+- `RECORD_AUDIO`: 'android.permission.RECORD_AUDIO'
+- `READ_PHONE_STATE`: 'android.permission.READ_PHONE_STATE'
+- `CALL_PHONE`: 'android.permission.CALL_PHONE'
+- `READ_CALL_LOG`: 'android.permission.READ_CALL_LOG'
+- `WRITE_CALL_LOG`: 'android.permission.WRITE_CALL_LOG'
+- `ADD_VOICEMAIL`: 'com.android.voicemail.permission.ADD_VOICEMAIL'
+- `USE_SIP`: 'android.permission.USE_SIP'
+- `PROCESS_OUTGOING_CALLS`: 'android.permission.PROCESS_OUTGOING_CALLS'
+- `BODY_SENSORS`: 'android.permission.BODY_SENSORS'
+- `SEND_SMS`: 'android.permission.SEND_SMS'
+- `RECEIVE_SMS`: 'android.permission.RECEIVE_SMS'
+- `READ_SMS`: 'android.permission.READ_SMS'
+- `RECEIVE_WAP_PUSH`: 'android.permission.RECEIVE_WAP_PUSH'
+- `RECEIVE_MMS`: 'android.permission.RECEIVE_MMS'
+- `READ_EXTERNAL_STORAGE`: 'android.permission.READ_EXTERNAL_STORAGE'
+- `WRITE_EXTERNAL_STORAGE`: 'android.permission.WRITE_EXTERNAL_STORAGE'
+- `BLUETOOTH_CONNECT`: 'android.permission.BLUETOOTH_CONNECT'
+- `BLUETOOTH_SCAN`: 'android.permission.BLUETOOTH_SCAN'
+- `BLUETOOTH_ADVERTISE`: 'android.permission.BLUETOOTH_ADVERTISE'
+- `ACCESS_MEDIA_LOCATION`: 'android.permission.ACCESS_MEDIA_LOCATION'
+- `ACCEPT_HANDOVER`: 'android.permission.ACCEPT_HANDOVER'
+- `ACTIVITY_RECOGNITION`: 'android.permission.ACTIVITY_RECOGNITION'
+- `ANSWER_PHONE_CALLS`: 'android.permission.ANSWER_PHONE_CALLS'
+- `READ_PHONE_NUMBERS`: 'android.permission.READ_PHONE_NUMBERS'
+- `UWB_RANGING`: 'android.permission.UWB_RANGING'
+- `BODY_SENSORS_BACKGROUND`: 'android.permission.BODY_SENSORS_BACKGROUND'
+- `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_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'
+
+### 请求权限的返回值
+
+返回值都以常量形式记录在`PermissionsAndroid.RESULTS`中:
+
+- `GRANTED`: 'granted', 表示用户已授权
+- `DENIED`: 'denied', 表示用户已拒绝
+- `NEVER_ASK_AGAIN`: 'never_ask_again',表示用户已拒绝,且不愿被再次询问。
+
+---
+
+# 文档
+
+## 方法
+
+### `check()`
+
+```tsx
+static check(permission: Permission): Promise;
+```
+
+检查某项权限是否经过用户授权。返回一个 promise,解析为布尔值。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ---------- | ------ | ---- | -------------- |
+| permission | string | 是 | 要检查的权限。 |
+
+---
+
+### `request()`
+
+```tsx
+static request(
+ permission: Permission,
+ rationale?: Rationale,
+): Promise;
+```
+
+弹出提示框向用户请求某项权限。返回一个 promise,最终值为上文所说的`PermissionsAndroid.RESULTS`。
+
+如果提供了`rationale`参数,则此方法会和系统协商,是弹出系统内置的权限申请对话框,还是显示`rationale`中的信息以向用户进行解释。具体原理请参阅 android 官方文档(https://developer.android.com/training/permissions/requesting.html#explain)。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ---------- | ------ | ---- | ------------------- |
+| permission | string | 是 | 要请求的权限 |
+| rationale | object | 否 | 见下面的`rationale` |
+
+**Rationale:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| -------------- | ------ | ---- | ---------------- |
+| title | string | 是 | 对话框的标题。 |
+| message | string | 是 | 对话框的正文。 |
+| buttonPositive | string | 是 | 同意按钮的文本。 |
+| buttonNegative | string | 否 | 拒绝按钮的文本。 |
+| buttonNeutral | string | 否 | 跳过按钮的文本。 |
+
+---
+
+### `requestMultiple()`
+
+```tsx
+static requestMultiple(
+ permissions: Permission[],
+): Promise<{[key in Permission]: PermissionStatus}>;
+```
+
+在一个弹出框中向用户请求多个权限。返回值为一个 object,key 为各权限名称,值为`PermissionsAndroid.RESULTS`。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ----------- | ----- | ---- | ------------------ |
+| permissions | array | Yes | 要申请的权限的数组 |
diff --git a/cnwebsite/versioned_docs/version-0.85/pixelratio.md b/cnwebsite/versioned_docs/version-0.85/pixelratio.md
new file mode 100644
index 00000000000..9a14aa60e7d
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/pixelratio.md
@@ -0,0 +1,175 @@
+---
+id: pixelratio
+title: PixelRatio
+---
+
+`PixelRatio` 可以获取到设备的像素密度和字体缩放比。
+
+## 根据像素密度获取指定大小的图片
+
+如果应用运行在一个高像素密度的设备上,显示的图片也应当分辨率更高。一个取得缩略图的好规则就是将显示尺寸乘以像素密度比:
+
+```
+const image = getImage({
+ width: PixelRatio.getPixelSizeForLayoutSize(200),
+ height: PixelRatio.getPixelSizeForLayoutSize(100),
+});
+
+```
+
+> 译注: 这段代码的意思是,如果你要在屏幕上摆放一个宽 200 高 100 的图片,那么首先要准备多个分辨率尺寸的图。`PixelRatio.getPixelSizeForLayoutSize(200)`方法会根据当前设备的 pixelratio 返回对应值,比如当前设备的 pixelratio 为 2,则返回 `200 \* 2 = 400`,最后生成的参数为`{ width: 400, height: 200 }`,然后开发者自己实现 getImage 方法,根据这一参数,返回最符合此尺寸的图片地址。
+
+## 像素网格对齐
+
+在 iOS 设备上,你可以给元素指定任意精度的坐标和尺寸,例如 29.674825。不过最终的物理屏幕上只会显示固定的坐标数。譬如 iPhone4 的分辨率是 640x960,而 iPhone6 是 750\*1334。iOS 会试图尽可能忠实地显示你指定的坐标,所以它采用了一种把一个像素分散到多个像素里的做法来欺骗眼睛。但这个作用的负面影响是显示出来的元素看起来会有一些模糊。
+
+在实践中,我们发现开发者们并不想要这个特性,反而需要去做一些额外的工作来确保坐标与像素坐标对齐,来避免元素显得模糊。在 React Native 中,我们会自动对齐坐标到像素坐标。
+
+我们做这个对齐的时候必须十分小心。如果你同时使用已经对齐的值和没有对齐的值,就会很容易产生一些因为近似导致的累积错误。即使这样的累积错误只发生一次,后果也可能会很严重,因为很可能会导致一个像素宽的边框最终突然消失或者显示为两倍的宽度。
+
+在 React Native 中,所有 JS 中的东西,包括布局引擎,都使用任意精度的数值。我们只在主线程最后设置原生组件的位置和坐标的时候才去做对齐工作。而且,对齐是相对于屏幕进行的,而非相对于父元素进行,进一步避免近似误差的累积。
+
+## 示例
+
+```SnackPlayer name=PixelRatio%20Example
+import React from 'react';
+import {
+ Image,
+ PixelRatio,
+ ScrollView,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const size = 50;
+const cat = {
+ uri: 'https://reactnative.dev/docs/assets/p_cat1.png',
+ width: size,
+ height: size,
+};
+
+const App = () => (
+
+
+
+
+ Current Pixel Ratio is:
+ {PixelRatio.get()}
+
+
+ Current Font Scale is:
+ {PixelRatio.getFontScale()}
+
+
+ On this device images with a layout width of
+ {size} px
+
+
+
+ require images with a pixel width of
+
+ {PixelRatio.getPixelSizeForLayoutSize(size)} px
+
+
+
+
+
+
+);
+
+const styles = StyleSheet.create({
+ scrollContainer: {
+ flex: 1,
+ },
+ container: {
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ value: {
+ fontSize: 24,
+ marginBottom: 12,
+ marginTop: 4,
+ },
+});
+
+export default App;
+```
+
+---
+
+# 文档
+
+## 方法
+
+### `get()`
+
+```jsx
+static get()
+```
+
+返回设备的像素密度,例如:
+
+- `PixelRatio.get() === 1`
+ - [mdpi Android devices](https://material.io/tools/devices/)
+- `PixelRatio.get() === 1.5`
+ - [hdpi Android devices](https://material.io/tools/devices/)
+- `PixelRatio.get() === 2`
+ - iPhone SE, 6S, 7, 8
+ - iPhone XR
+ - iPhone 11
+ - [xhdpi Android devices](https://material.io/tools/devices/)
+- `PixelRatio.get() === 3`
+ - iPhone 6S Plus, 7 Plus, 8 Plus
+ - iPhone X, XS, XS Max
+ - iPhone 11 Pro, 11 Pro Max
+ - Pixel, Pixel 2
+ - [xxhdpi Android devices](https://material.io/tools/devices/)
+- `PixelRatio.get() === 3.5`
+ - Nexus 6
+ - Pixel XL, Pixel 2 XL
+ - [xxxhdpi Android devices](https://material.io/tools/devices/)
+
+---
+
+### `getFontScale()`
+
+```jsx
+static getFontScale(): number
+```
+
+返回字体大小缩放比例。这个比例可以用于计算绝对的字体大小,所以很多深度依赖字体大小的组件需要用此函数的结果进行计算。
+
+- Android 上对应的是用户选项里的“设置 > 显示 > 字体大小”。
+- iOS 上对应的是用户选项里的**Settings > Display & Brightness > Text Size**, value can also be updated in **Settings > Accessibilty > Display & Test Size > Larger Text**
+
+如果没有设置字体缩放大小,它会直接返回设备的像素密度。
+
+---
+
+### `getPixelSizeForLayoutSize()`
+
+```jsx
+static getPixelSizeForLayoutSize(layoutSize: number): number
+```
+
+将一个布局尺寸(dp)转换为像素尺寸(px)。
+
+一定会返回一个整数数值。
+
+---
+
+### `roundToNearestPixel()`
+
+```jsx
+static roundToNearestPixel(layoutSize)
+```
+
+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/cnwebsite/versioned_docs/version-0.85/platform-specific-code.md b/cnwebsite/versioned_docs/version-0.85/platform-specific-code.md
new file mode 100644
index 00000000000..c38757b3f30
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/platform-specific-code.md
@@ -0,0 +1,134 @@
+---
+id: platform-specific-code
+title: 特定平台代码
+---
+
+在编写跨平台的应用时,我们肯定希望尽可能多地复用代码。但是总有些时候我们会碰到针对不同平台编写不同代码的需求。
+
+React Native 提供了两种方法来区分平台:
+
+- 使用[`Platform`模块](platform-specific-code.md#platform模块).
+- 使用[特定平台后缀](platform-specific-code.md#特定平台后缀).
+
+另外有些内置组件的某些属性可能只在特定平台上有效。请在阅读文档时留意。
+
+## Platform 模块
+
+React Native 提供了一个检测当前运行平台的模块。如果组件只有一小部分代码需要依据平台定制,那么这个模块就可以派上用场。
+
+```jsx
+import {Platform, StyleSheet} from 'react-native';
+
+const styles = StyleSheet.create({
+ height: Platform.OS === 'ios' ? 200 : 100,
+});
+```
+
+`Platform.OS`在 iOS 上会返回`ios`,而在 Android 设备或模拟器上则会返回`android`。
+
+还有个实用的方法是 Platform.select(),它可以以 Platform.OS 为 key,从传入的对象中返回对应平台的值,见下面的示例:
+
+```jsx
+import {Platform, StyleSheet} from 'react-native';
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ ...Platform.select({
+ ios: {
+ backgroundColor: 'red',
+ },
+ android: {
+ backgroundColor: 'green',
+ },
+ default: {
+ // other platforms, web for example
+ backgroundColor: 'blue',
+ },
+ }),
+ },
+});
+```
+
+上面的代码会根据平台的不同返回不同的 container 样式 —— iOS 上背景色为红色,android 为绿色,其他平台(如 web)为蓝色。
+
+这一方法可以接受任何合法类型的参数,因此你也可以直接用它针对不同平台返回不同的组件,像下面这样:
+
+```jsx
+const Component = Platform.select({
+ ios: () => require('ComponentIOS'),
+ android: () => require('ComponentAndroid'),
+})();
+
+ ;
+```
+
+```jsx
+const Component = Platform.select({
+ native: () => require('ComponentForNative'),
+ default: () => require('ComponentForWeb'),
+})();
+
+ ;
+```
+
+### 检测 Android 版本
+
+在 Android 上,`Version`属性是一个数字,表示 Android 的 api level:
+
+```jsx
+import {Platform} from 'react-native';
+
+if (Platform.Version === 25) {
+ console.log('Running on Nougat!');
+}
+```
+
+### 检测 iOS 版本
+
+在 iOS 上,`Version`属性是`-[UIDevice systemVersion]`的返回值,具体形式为一个表示当前系统版本的字符串。比如可能是"10.3"。
+
+```jsx
+import {Platform} from 'react-native';
+
+const majorVersionIOS = parseInt(Platform.Version, 10);
+if (majorVersionIOS <= 9) {
+ console.log('Work around a change in behavior');
+}
+```
+
+## 特定平台后缀
+
+当不同平台的代码逻辑较为复杂时,最好是放到不同的文件里,这时候我们可以使用特定平台后缀。React Native 会检测某个文件是否具有`.ios.`或是`.android.`的后缀,然后根据当前运行的平台自动加载正确对应的文件。
+
+比如你可以在项目中创建下面这样的组件:
+
+```sh
+BigButton.ios.js
+BigButton.android.js
+```
+
+然后去掉平台后缀直接引用:
+
+```jsx
+import BigButton from './BigButton';
+```
+
+React Native 会根据运行平台的不同自动引入正确对应的组件。
+
+如果你还希望在 web 端复用 React Native 的代码,那么还可以使用`.native.js`的后缀。此时 iOS 和 Android 会使用`BigButton.native.js`文件,而 web 端会使用`BigButton.js`。(注意目前官方并没有直接提供 web 端的支持,请在社区搜索第三方方案)。
+
+比如在你的项目中存在如下的两个文件:
+
+```sh
+Container.js # 由 Webpack, Rollup 或者其他打包工具打包的文件
+Container.native.js # 由 React Native 自带打包工具(Metro) 为ios和android 打包的文件
+```
+
+在引用时并不需要添加`.native.`后缀:
+
+```jsx
+import Container from './Container';
+```
+
+**提示:** 为避免在构建后的 Web 生产环境的代码中出现多余代码,要记得在你的 Web 打包工具中配置忽略`.native.js`结尾的文件, 这样可以减少打包后文件的大小。
diff --git a/cnwebsite/versioned_docs/version-0.85/platform.md b/cnwebsite/versioned_docs/version-0.85/platform.md
new file mode 100644
index 00000000000..809a3f4ccfc
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/platform.md
@@ -0,0 +1,246 @@
+---
+id: platform
+title: Platform
+---
+
+## 示例
+
+```SnackPlayer name=Platform%20API%20Example&supportedPlatforms=ios,android
+import React from 'react';
+import {Platform, StyleSheet, Text, ScrollView} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ return (
+
+
+
+ OS
+ {Platform.OS}
+ OS Version
+ {Platform.Version}
+ isTV
+ {Platform.isTV.toString()}
+ {Platform.OS === 'ios' && (
+ <>
+ isPad
+ {Platform.isPad.toString()}
+ >
+ )}
+ Constants
+
+ {JSON.stringify(Platform.constants, null, 2)}
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ value: {
+ fontWeight: '600',
+ padding: 4,
+ marginBottom: 8,
+ },
+ safeArea: {
+ flex: 1,
+ },
+});
+
+export default App;
+```
+
+---
+
+# 参考
+
+## 属性
+
+### `constants`
+
+```tsx
+static constants: PlatformConstants;
+```
+
+返回一个包含当前平台所有可用通用常量和平台特定常量的对象。
+
+**属性:**
+
+| 名称
| 类型 | 可选 | 说明 |
+| --------------------------------------------------------- | ------- | ---- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| isTesting | boolean | 否 | |
+| reactNativeVersion | object | 否 | React Native 版本信息。键为 `major`、`minor`、`patch`(可选 `prerelease`),值为 `number` 类型。 |
+| Version Android
| number | 否 | Android 特定的操作系统版本常量。 |
+| Release Android
| string | 否 | |
+| Serial Android
| string | 否 | Android 设备的硬件序列号。 |
+| Fingerprint Android
| string | 否 | 唯一标识该构建版本的字符串。 |
+| Model Android
| string | 否 | 面向最终用户的 Android 设备名称。 |
+| Brand Android
| string | 否 | 产品/硬件关联的消费者可见品牌名称。 |
+| Manufacturer Android
| string | 否 | Android 设备的制造商。 |
+| ServerHost Android
| string | 是 | |
+| uiMode Android
| string | 否 | 可能的值有:`'car'`、`'desk'`、`'normal'`、`'tv'`、`'watch'` 和 `'unknown'`。详见 [Android ModeType](https://developer.android.com/reference/android/app/UiModeManager.html)。 |
+| forceTouchAvailable iOS
| boolean | 否 | 指示设备是否支持 3D Touch。 |
+| interfaceIdiom iOS
| string | 否 | 设备的界面类型。详见 [UIUserInterfaceIdiom](https://developer.apple.com/documentation/uikit/uiuserinterfaceidiom)。 |
+| osVersion iOS
| string | 否 | iOS 特定的操作系统版本常量。 |
+| systemName iOS
| string | 否 | iOS 特定的操作系统名称常量。 |
+
+---
+
+### `isPad` iOS
+
+```tsx
+static isPad: boolean;
+```
+
+返回一个布尔值,指示当前设备是否为 iPad。
+
+| 类型 |
+| ------- |
+| boolean |
+
+---
+
+### `isTV`
+
+```tsx
+static isTV: boolean;
+```
+
+返回一个布尔值,指示当前设备是否为电视。
+
+| 类型 |
+| ------- |
+| boolean |
+
+---
+
+### `isVision`
+
+```tsx
+static isVision: boolean;
+```
+
+返回一个布尔值,指示当前设备是否为 Apple Vision 设备。_如果你使用的是 [Apple Vision Pro(Designed for iPad)](https://developer.apple.com/documentation/visionos/determining-whether-to-bring-your-app-to-visionos),`isVision` 将为 `false`,但 `isPad` 将为 `true`。_
+
+| 类型 |
+| ------- |
+| boolean |
+
+---
+
+### `isTesting`
+
+```tsx
+static isTesting: boolean;
+```
+
+返回一个布尔值,指示应用是否在开发者模式下且设置了测试标记时运行。
+
+| 类型 |
+| ------- |
+| boolean |
+
+---
+
+### `OS`
+
+```tsx
+static OS: 'android' | 'ios';
+```
+
+返回表示当前操作系统的字符串值。
+
+| 类型 |
+| -------------------------- |
+| enum(`'android'`, `'ios'`) |
+
+---
+
+### `Version`
+
+```tsx
+static Version: 'number' | 'string';
+```
+
+返回操作系统的版本号。
+
+| 类型 |
+| ---------------------------------------------------------------------------------------------------- |
+| number Android
string iOS
|
+
+## 方法
+
+### `select()`
+
+```tsx
+static select(config: Record): T;
+```
+
+根据当前运行的平台返回最匹配的值。
+
+#### 参数:
+
+| 名称 | 类型 | 必填 | 说明 |
+| ------ | ------ | ---- | ------------------ |
+| config | object | 是 | 详见下方配置说明。 |
+
+`select` 方法返回当前运行平台最匹配的值。即如果你在手机上运行,`android` 和 `ios` 键会优先匹配。如果这两个键未指定,则会使用 `native` 键,最后才使用 `default` 键。
+
+`config` 参数是一个对象,可包含以下键:
+
+- `android` (any)
+- `ios` (any)
+- `native` (any)
+- `default` (any)
+
+**使用示例:**
+
+```tsx
+import {Platform, StyleSheet} from 'react-native';
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ ...Platform.select({
+ android: {
+ backgroundColor: 'green',
+ },
+ ios: {
+ backgroundColor: 'red',
+ },
+ default: {
+ // 其他平台,例如 Web
+ backgroundColor: 'blue',
+ },
+ }),
+ },
+});
+```
+
+上述代码会使容器在所有平台上都具有 `flex: 1`,在 Android 上背景为绿色,在 iOS 上背景为红色,在其他平台上背景为蓝色。
+
+由于对应平台键的值可以是任意类型,[`select`](platform.md#select) 方法也可以用于返回平台特定的组件,如下所示:
+
+```tsx
+const Component = Platform.select({
+ ios: () => require('ComponentIOS'),
+ android: () => require('ComponentAndroid'),
+})();
+
+ ;
+```
+
+```tsx
+const Component = Platform.select({
+ native: () => require('ComponentForNative'),
+ default: () => require('ComponentForWeb'),
+})();
+
+ ;
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/platformcolor.md b/cnwebsite/versioned_docs/version-0.85/platformcolor.md
new file mode 100644
index 00000000000..f950551c41e
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/platformcolor.md
@@ -0,0 +1,91 @@
+---
+id: platformcolor
+title: PlatformColor
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+```js
+PlatformColor(color1, [color2, ...colorN]);
+```
+
+您可以使用 `PlatformColor` 函数通过提供原生颜色的相应字符串值来访问目标平台上的原生颜色。您将一个字符串传递给 `PlatformColor` 函数,如果该字符串在该平台上存在,它将返回相应的原生颜色,您可以在应用程序的任何部分应用该颜色。
+
+如果您向 `PlatformColor` 函数传递多个字符串值,它会将第一个值视为默认值,其余的作为备选值。
+
+```js
+PlatformColor('bogusName', 'linkColor');
+```
+
+由于原生颜色可能对主题和/或高对比度敏感,因此这种特定于平台的逻辑也会转换到您的组件内部。
+
+### 支持的颜色
+
+有关支持的系统颜色类型的完整列表,请参阅:
+
+- Android:
+ - [R.attr](https://developer.android.com/reference/android/R.attr) - `?attr` 前缀
+ - [R.color](https://developer.android.com/reference/android/R.color) - `@android:color` 前缀
+- iOS (Objective-C 和 Swift 表示法):
+ - [UIColor 标准颜色](https://developer.apple.com/documentation/uikit/uicolor/standard_colors)
+ - [UIColor UI 元素颜色](https://developer.apple.com/documentation/uikit/uicolor/ui_element_colors)
+
+#### 开发者笔记
+
+
+
+
+
+:::info
+如果您熟悉设计系统,另一种思考方式是 `PlatformColor` 让您可以利用本地设计系统的颜色令牌,这样您的应用就可以完美融入!
+:::
+
+
+
+
+## 示例
+
+```SnackPlayer name=PlatformColor%20Example&supportedPlatforms=android,ios
+import React from 'react';
+import {Platform, PlatformColor, StyleSheet, Text} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => (
+
+
+ I am a special label color!
+
+
+);
+
+const styles = StyleSheet.create({
+ label: {
+ padding: 16,
+ fontWeight: '800',
+ ...Platform.select({
+ ios: {
+ color: PlatformColor('label'),
+ backgroundColor: PlatformColor('systemTealColor'),
+ },
+ android: {
+ color: PlatformColor('?android:attr/textColor'),
+ backgroundColor: PlatformColor('@android:color/holo_blue_bright'),
+ },
+ default: {color: 'black'},
+ }),
+ },
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
+
+export default App;
+```
+
+提供给 `PlatformColor` 函数的字符串值必须与应用程序运行的原生平台上存在的字符串匹配。为了避免运行时错误,该函数应该包装在平台检查中,可以通过 `Platform.OS === 'platform'` 或 `Platform.select()`,如上面的示例所示。
+
+:::note
+您可以在 [PlatformColorExample.js](https://github.com/facebook/react-native/blob/main/packages/rn-tester/js/examples/PlatformColor/PlatformColorExample.js) 中找到一个完整的示例,演示了 `PlatformColor` 的正确预期用法。
+:::
diff --git a/cnwebsite/versioned_docs/version-0.85/pressable.md b/cnwebsite/versioned_docs/version-0.85/pressable.md
new file mode 100644
index 00000000000..85cbc5056b0
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/pressable.md
@@ -0,0 +1,268 @@
+---
+id: pressable
+title: Pressable
+---
+
+`Pressable` 是一个核心组件的封装,它可以检测到任意子组件的不同阶段的按压交互情况。
+
+```tsx
+
+ I'm pressable!
+
+```
+
+## 原理
+
+在被 `Pressable` 包装的元素上:
+
+- [`onPressIn`](#onpressin) 在按压时被调用。
+- [`onPressOut`](#onpressout) 在按压动作结束后被调用。
+
+在按下 [`onPressIn`](#onpressin) 后,将会出现如下两种情况的一种:
+
+1. 用户移开手指,依次触发 [`onPressOut`](#onpressout) 和 [`onPress`](#onpress) 事件。
+2. 按压持续 500 毫秒以上,触发 [`onLongPress`](#onlongpress) 事件。([`onPressOut`](#onpressout) 在移开手后依旧会触发。)
+
+
+
+手指的精准度终究不是很精确,人们经常会不小心按错了或者错过了触发区域。为了帮助解决这个问题,`Pressable` 提供了一个可选项 `HitRect`,可以用来定义相对于包裹元素的有效触控距离。在 `HitRect` 内的任何地方都可以触发按压动作。
+
+`PressRect` 在保持激活状态的同时,允许用户按压时在元素及设定的范围内滑动,使触控更加优雅。试想一下缓慢地滑动着离开按下的按钮。
+
+:::note
+触控区域不会超出绑定的父级 view,在按压到重叠的兄弟视图时,z-index 更高的那个视图会更优先。
+:::
+
+
+
+
+ 用 hitSlop 设置 HitRect;用 pressRetentionOffset 设置 PressRect。
+
+
+
+:::info
+`Pressable` 使用了 React Native 的 `Pressability` API。查看 [Pressability](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Pressability/Pressability.js#L350) 的实现,了解更多关于 Pressability 的状态机流程和原理。
+:::
+
+## 示例
+
+```SnackPlayer name=Pressable
+import React, {useState} from 'react';
+import {Pressable, StyleSheet, Text, View} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ const [timesPressed, setTimesPressed] = useState(0);
+
+ let textLog = '';
+ if (timesPressed > 1) {
+ textLog = timesPressed + 'x onPress';
+ } else if (timesPressed > 0) {
+ textLog = 'onPress';
+ }
+
+ return (
+
+
+ {
+ setTimesPressed(current => current + 1);
+ }}
+ style={({pressed}) => [
+ {
+ backgroundColor: pressed ? 'rgb(210, 230, 255)' : 'white',
+ },
+ styles.wrapperCustom,
+ ]}>
+ {({pressed}) => (
+ {pressed ? 'Pressed!' : 'Press Me'}
+ )}
+
+
+ {textLog}
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ },
+ text: {
+ fontSize: 16,
+ },
+ wrapperCustom: {
+ borderRadius: 8,
+ padding: 6,
+ },
+ logBox: {
+ padding: 20,
+ margin: 10,
+ borderWidth: StyleSheet.hairlineWidth,
+ borderColor: '#f0f0f0',
+ backgroundColor: '#f9f9f9',
+ },
+});
+
+export default App;
+```
+
+## Props
+
+### `android_disableSound` Android
+
+为 true 时,按下不会播放 Android 系统声音。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `false` |
+
+### `android_ripple` Android
+
+使用并配置 Android 波纹效果。
+
+| Type |
+| -------------------------------------- |
+| [RippleConfig](pressable#rippleconfig) |
+
+### `children`
+
+接收按压状态布尔值的子节点或函数。
+
+| Type |
+| ------------------------ |
+| [React Node](react-node) |
+
+### `unstable_pressDelay`
+
+按下后到调用 `onPressIn` 之前的等待时长(毫秒)。
+
+| Type |
+| ------ |
+| number |
+
+### `delayLongPress`
+
+从 `onPressIn` 触发到 `onLongPress` 被调用的时间间隔(毫秒)。
+
+| Type | Default |
+| ------ | ------- |
+| number | `500` |
+
+### `disabled`
+
+是否禁用按压行为。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `false` |
+
+### `hitSlop`
+
+设置元素能够检测到按压动作的额外距离。
+
+| Type |
+| ---------------------- |
+| [Rect](rect) or number |
+
+### `onHoverIn`
+
+当悬停激活时调用,用于提供视觉反馈。
+
+| Type |
+| --------------------------------------------------------------------------------------------------------- |
+| `md ({ nativeEvent: [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) }) => void` |
+
+### `onHoverOut`
+
+当悬停结束时调用,用于撤销视觉反馈。
+
+| Type |
+| --------------------------------------------------------------------------------------------------------- |
+| `md ({ nativeEvent: [MouseEvent](https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent) }) => void` |
+
+### `onLongPress`
+
+在 `onPressIn` 持续超过 500 毫秒后调用。此持续时间可以通过 [`delayLongPress`](#delaylongpress) 自定义。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+### `onPress`
+
+`onPressOut` 之后调用。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+### `onPressIn`
+
+在 `onPressOut` 和 `onPress` 之前,按压后立即调用。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+### `onPressMove`
+
+按压位置移动时调用。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+### `onPressOut`
+
+松开手后调用。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+### `pressRetentionOffset`
+
+在 `onPressOut` 被触发前,view 额外的有效触控距离。
+
+| Type | Default |
+| ---------------------- | -------------------------------------------- |
+| [Rect](rect) or number | `{bottom: 30, left: 20, right: 20, top: 20}` |
+
+### `style`
+
+可使用普通视图样式,或者一个函数来根据按压状态布尔值返回视图样式。
+
+| Type |
+| ----------------------------------------------------------------------------------------------- |
+| [View Style](view-style-props) 或 `md ({ pressed: boolean }) => [View Style](view-style-props)` |
+
+### `testOnly_pressed`
+
+仅用于指导文档或测试(比如快照测试)。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `false` |
+
+## 类型定义
+
+### RippleConfig
+
+`android_ripple` 属性的波纹效果配置。
+
+| Type |
+| ------ |
+| object |
+
+**Properties:**
+
+| Name | Type | Required | Description |
+| ---------- | --------------- | -------- | ---------------------------------------------------------------------------------------------------------------------------- |
+| color | [color](colors) | No | 定义波纹的颜色。 |
+| borderless | boolean | No | 定义波纹效果是否包含边框。 |
+| radius | number | No | 定义波纹的半径。 |
+| foreground | boolean | No | 设为 true 可将波纹效果添加到视图的前景而非背景。当子视图有自己的背景色或者你在显示图片时,这很有用,可以避免波纹效果被遮挡。 |
diff --git a/cnwebsite/versioned_docs/version-0.85/pressevent.md b/cnwebsite/versioned_docs/version-0.85/pressevent.md
new file mode 100644
index 00000000000..768d1d0f891
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/pressevent.md
@@ -0,0 +1,118 @@
+---
+id: pressevent
+title: 点击事件对象
+---
+
+点击事件对象作为用户按压交互的结果在回调中返回,例如 [Button](button) 组件中的 `onPress`。
+
+## 示例
+
+```js
+{
+ changedTouches: [PressEvent],
+ identifier: 1,
+ locationX: 8,
+ locationY: 4.5,
+ pageX: 24,
+ pageY: 49.5,
+ target: 1127,
+ timestamp: 85131876.58868201,
+ touches: []
+}
+```
+
+## 属性与值
+
+### `changedTouches`
+
+自上次事件以来发生变化的所有点击事件对象数组。
+
+| 类型 | 可选 |
+| ---------------- | ---- |
+| 点击事件对象数组 | 否 |
+
+### `force` iOS
+
+3D Touch 按压期间使用的力度。返回范围从 `0.0` 到 `1.0` 的浮点值。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 是 |
+
+### `identifier`
+
+为事件分配的唯一数字标识符。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `locationX`
+
+在可触摸区域内触摸原点的 X 坐标(相对于元素)。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `locationY`
+
+在可触摸区域内触摸原点的 Y 坐标(相对于元素)。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `pageX`
+
+触摸原点在屏幕上的 X 坐标(相对于根视图)。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `pageY`
+
+触摸原点在屏幕上的 Y 坐标(相对于根视图)。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `target`
+
+接收点击事件对象的元素的节点 id。
+
+| 类型 | 可选 |
+| --------------------------- | ---- |
+| number, `null`, `undefined` | 否 |
+
+### `timestamp`
+
+当点击事件对象发生时的时间戳。值以毫秒为单位表示。
+
+| 类型 | 可选 |
+| ------ | ---- |
+| number | 否 |
+
+### `touches`
+
+屏幕上所有当前点击事件对象的数组。
+
+| 类型 | 可选 |
+| ---------------- | ---- |
+| 点击事件对象数组 | 否 |
+
+## 使用点击事件对象的组件
+
+- [`Button`](button)
+- [`PanResponder`](panresponder)
+- [`Pressable`](pressable)
+- [`ScrollView`](scrollview)
+- [`Text`](text)
+- [`TextInput`](textinput)
+- [`TouchableHighlight`](touchablenativefeedback)
+- [`TouchableOpacity`](touchablewithoutfeedback)
+- [`TouchableNativeFeedback`](touchablenativefeedback)
+- [`TouchableWithoutFeedback`](touchablewithoutfeedback)
+- [`View`](view)
diff --git a/cnwebsite/versioned_docs/version-0.85/profiling.md b/cnwebsite/versioned_docs/version-0.85/profiling.md
new file mode 100644
index 00000000000..d2e04b5dbe8
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/profiling.md
@@ -0,0 +1,139 @@
+---
+id: profiling
+title: 性能分析
+---
+
+性能分析是分析应用程序的性能、资源使用情况和行为以识别潜在瓶颈或低效率的过程。使用性能分析工具来确保您的应用在不同设备和条件下流畅运行是非常值得的。
+
+对于 iOS,Instruments 是一个非常宝贵的工具,而在 Android 上,您应该学习使用 [Android Studio Profiler](profiling.md#profiling-android-ui-performance-with-system-tracing)。
+
+但首先,[**确保开发模式已关闭!**](performance.md#running-in-development-mode-devtrue)
+
+## 使用系统跟踪分析 Android UI 性能
+
+Android 支持 10k+ 不同的手机,并被泛化以支持软件渲染:框架架构和需要跨多个硬件目标泛化的需求不幸意味着相对于 iOS,您获得的免费优化较少。但有时,您可以改进一些东西 —— 而且很多时候根本不是原生代码的问题!
+
+调试这种卡顿的第一步是回答一个基本问题:在每个 16ms 帧期间,您的时间花在哪里。为此,我们将使用 [Android Studio 中内置的系统跟踪分析器](https://developer.android.com/studio/profile)。
+
+### 1. 收集跟踪
+
+首先,通过 USB 将表现出您想要调查的卡顿的设备连接到计算机。在 Android Studio 中打开项目的 `android` 文件夹,在右上方窗格中选择您的设备,然后[以可分析模式运行您的项目](https://developer.android.com/studio/profile#build-and-run)。
+
+当您的应用以可分析模式构建并在设备上运行时,将应用调整到您想要分析的导航/动画之前的位置,然后在 Android Studio Profiler 窗格中启动["捕获系统活动"任务](https://developer.android.com/studio/profile#start-profiling)。
+
+一旦跟踪开始收集,执行您关心的动画或交互。然后按"停止录制"。您现在可以[直接在 Android Studio 中检查跟踪](https://developer.android.com/studio/profile/jank-detection)。或者,您可以在"过去的录制"窗格中选择它,按"导出录制",然后在 [Perfetto](https://perfetto.dev/) 等工具中打开它。
+
+### 2. 阅读跟踪
+
+在 Android Studio 或 Perfetto 中打开跟踪后,您应该会看到类似这样的内容:
+
+
+
+:::note 提示
+使用 WASD 键进行平移和缩放。
+:::
+
+具体的 UI 可能不同,但无论您使用哪种工具,以下说明都适用。
+
+:::info 启用 VSync 高亮
+勾选屏幕右上角的此复选框以突出显示 16ms 帧边界:
+
+
+
+您应该看到如上面屏幕截图中的斑马条纹。如果没有看到,请尝试在不同设备上进行分析:众所周知,三星在显示 vsyncs 方面存在问题,而 Nexus 系列通常相当可靠。
+:::
+
+### 3. 查找您的进程
+
+滚动直到您看到包名称的(部分)。在这种情况下,我正在分析 `com.facebook.adsmanager`,它显示为 `book.adsmanager`,因为内核中愚蠢的线程名称限制。
+
+在左侧,您将看到一组线程,它们对应于右侧的时间线行。有几个我们关心的线程:UI 线程(具有您的包名称或名称 UI Thread)、`mqt_js` 和 `mqt_native_modules`。如果您在 Android 5+ 上运行,我们还关心 Render Thread。
+
+- **UI Thread(UI 线程)。** 这是标准 Android 测量/布局/绘制发生的地方。右侧的线程名称将是您的包名称(在我的例子中是 book.adsmanager)或 UI Thread。您在此线程上看到的事件应该看起来像这样,并且与 `Choreographer`、`traversals` 和 `DispatchUI` 有关:
+
+ 
+
+- **JS Thread(JS 线程)。** 这是执行 JavaScript 的地方。线程名称将是 `mqt_js` 或 `<...>`,具体取决于设备上的内核有多配合。如果它没有名称,要识别它,请查找 `JSCall`、`Bridge.executeJSCall` 等:
+
+ 
+
+- **Native Modules Thread(原生模块线程)。** 这是执行原生模块调用(例如 `UIManager`)的地方。线程名称将是 `mqt_native_modules` 或 `<...>`。要在后一种情况下识别它,请查找 `NativeCall`、`callJavaModuleMethod` 和 `onBatchComplete` 等:
+
+ 
+
+- **额外:Render Thread(渲染线程)。** 如果您使用的是 Android L (5.0) 及更高版本,您的应用程序中还将有一个渲染线程。此线程生成用于绘制 UI 的实际 OpenGL 命令。线程名称将是 `RenderThread` 或 `<...>`。要在后一种情况下识别它,请查找 `DrawFrame` 和 `queueBuffer` 等:
+
+ 
+
+## 识别罪魁祸首
+
+流畅的动画应该看起来像下面这样:
+
+
+
+每次颜色变化都是一帧 —— 请记住,为了显示一帧,我们所有的 UI 工作都需要在 16ms 期间结束之前完成。请注意,没有线程在接近帧边界的地方工作。像这样渲染的应用程序以 60 FPS 渲染。
+
+但是,如果您注意到卡顿,您可能会看到如下内容:
+
+
+
+请注意,JS 线程几乎一直在执行,并且跨越了帧边界!此应用程序未以 60 FPS 渲染。在这种情况下,**问题出在 JS 中**。
+
+您也可能看到如下内容:
+
+
+
+在这种情况下,UI 和渲染线程是跨越帧边界的工作线程。我们试图在每一帧上渲染的 UI 需要完成太多工作。在这种情况下,**问题出在正在渲染的原生视图中**。
+
+此时,您将获得一些非常有用的信息来指导您的下一步。
+
+## 解决 JavaScript 问题
+
+如果您发现了 JS 问题,请在您正在执行的特定 JS 中寻找线索。在上面的场景中,我们看到 `RCTEventEmitter` 每帧被调用多次。这是上面跟踪中 JS 线程的放大图:
+
+
+
+这似乎不对。为什么它被调用得如此频繁?它们实际上是不同的事件吗?这些问题的答案可能取决于您的产品代码。很多时候,您需要查看 [shouldComponentUpdate](https://react.dev/reference/react/Component#shouldcomponentupdate)。
+
+## 解决原生 UI 问题
+
+如果您发现了原生 UI 问题,通常有两种情况:
+
+1. 您试图在每一帧上绘制的 UI 涉及 GPU 上的太多工作,或
+2. 您在动画/交互期间构造新的 UI(例如,在滚动期间加载新内容)。
+
+### GPU 工作过多
+
+在第一种情况下,您将看到一个跟踪,其中 UI 线程和/或渲染线程看起来像这样:
+
+
+
+注意在 `DrawFrame` 中花费的大量时间跨越了帧边界。这是等待 GPU 从上一帧排空其命令缓冲区所花费的时间。
+
+要缓解这个问题,您应该:
+
+- 调查对正在进行动画/转换的复杂静态内容使用 `renderToHardwareTextureAndroid`(例如 `Navigator` 滑动/alpha 动画)
+- 确保您**没有**使用 `needsOffscreenAlphaCompositing`,它默认是禁用的,因为在大多数情况下,它会大大增加 GPU 的每帧负载。
+
+### 在 UI 线程上创建新视图
+
+在第二种情况下,您将看到更像这样的内容:
+
+
+
+注意首先 JS 线程思考了一会儿,然后您会看到在原生模块线程上完成的一些工作,然后是 UI 线程上的一个昂贵的遍历。
+
+除非您能够推迟在交互之后创建新 UI,或者您能够简化正在创建的 UI,否则没有快速的方法来缓解这个问题。React Native 团队正在开发一个基础设施级解决方案,该方案将允许在主线程之外创建和配置新 UI,从而允许交互继续顺畅进行。
+
+### 查找原生 CPU 热点
+
+如果问题似乎在原生端,您可以使用 [CPU 热点分析器](https://developer.android.com/studio/profile/record-java-kotlin-methods)获取有关正在发生的事情的更多详细信息。打开 Android Studio Profiler 面板并选择"查找 CPU 热点(Java/Kotlin 方法录制)"。
+
+:::info 选择 Java/Kotlin 录制
+
+确保选择"查找 CPU 热点 **(Java/Kotlin 录制)**"而不是"查找 CPU 热点(调用栈采样)"。它们具有相似的图标但执行不同的操作。
+:::
+
+执行交互并按"停止录制"。录制是资源密集型的,因此保持交互简短。然后,您可以在 Android Studio 中检查生成的跟踪,或将其导出并在 [Firefox Profiler](https://profiler.firefox.com/) 等在线工具中打开它。
+
+与系统跟踪不同,CPU 热点分析速度很慢,因此不会给您准确的测量结果。但是,它应该让您了解正在调用哪些原生方法,以及在每一帧期间时间按比例花在哪里。
diff --git a/cnwebsite/versioned_docs/version-0.85/progressbarandroid.md b/cnwebsite/versioned_docs/version-0.85/progressbarandroid.md
new file mode 100644
index 00000000000..d082ff11aea
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/progressbarandroid.md
@@ -0,0 +1,131 @@
+---
+id: progressbarandroid
+title: '🗑️ ProgressBarAndroid'
+---
+
+:::warning Deprecated
+Use one of the [community packages](https://reactnative.directory/?search=progressbar) instead.
+:::
+
+封装了 Android 平台上的`ProgressBar`的 React 组件。这个组件可以用来表示应用正在加载或者有些事情正在进行中。
+
+### 示例
+
+```SnackPlayer name=ProgressBarAndroid&supportedPlatforms=android
+import React from 'react';
+import {View, StyleSheet, ProgressBarAndroid, Text} from 'react-native';
+
+const App = () => {
+ return (
+
+
+ Circle Progress Indicator
+
+
+
+ Horizontal Progress Indicator
+
+
+
+ Colored Progress Indicator
+
+
+
+ Fixed Progress Value
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ example: {
+ marginVertical: 24,
+ },
+});
+
+export default App;
+```
+
+---
+
+# 文档
+
+## Props
+
+继承 [View Props](view.md#props).
+
+### `animating`
+
+是否显示进度条(默认为 true 显示)。
+
+| 类型 | 必需 |
+| ---- | ---- |
+| bool | 否 |
+
+---
+
+### `color`
+
+进度条的颜色。
+
+| 类型 | 必需 |
+| ------------------ | ---- |
+| [color](colors.md) | 否 |
+
+---
+
+### `indeterminate`
+
+决定进度条是否要显示一个不确定的进度。注意这个在 styleAttr 是 Horizontal 的时候必须是 false,并且需要设置`progress`值。
+
+| 类型 | 必需 |
+| ----------------- | ---- |
+| indeterminateType | 否 |
+
+---
+
+### `progress`
+
+当前的进度值(在 0 到 1 之间)。
+
+| 类型 | 必需 |
+| ------ | ---- |
+| number | 否 |
+
+---
+
+### `styleAttr`
+
+进度条的样式。可取值有:
+
+- Horizontal
+- Normal (default)
+- Small
+- Large
+- Inverse
+- SmallInverse
+- LargeInverse
+
+| 类型 | 必需 |
+| ----------------------------------------------------------------------------------------- | ---- |
+| enum('Horizontal', 'Normal', 'Small', 'Large', 'Inverse', 'SmallInverse', 'LargeInverse') | 否 |
+
+---
+
+### `testID`
+
+用来在端到端测试中定位这个视图。
+
+| 类型 | 必需 |
+| ------ | ---- |
+| string | 否 |
diff --git a/cnwebsite/versioned_docs/version-0.85/props.md b/cnwebsite/versioned_docs/version-0.85/props.md
new file mode 100644
index 00000000000..4c1cedb5131
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/props.md
@@ -0,0 +1,99 @@
+---
+id: props
+title: Props(属性)
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+大多数组件在创建时就可以使用各种参数来进行定制。用于定制的这些参数就称为`props`(属性)。
+
+以常见的基础组件`Image`为例,在创建一个图片时,可以传入一个名为`source`的 prop 来指定要显示的图片的地址,以及使用名为`style`的 prop 来控制其尺寸。
+
+```SnackPlayer name=Props
+import React from 'react';
+import {Image} from 'react-native';
+
+const Bananas = () => {
+ let pic = {
+ uri: 'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg',
+ };
+ return (
+
+ );
+};
+
+export default Bananas;
+```
+
+请注意`{pic}`外围有一层括号,我们需要用括号来把`pic`这个变量嵌入到 JSX 语句中。括号的意思是括号内部为一个 js 变量或表达式,需要执行后取值。因此我们可以把任意合法的 JavaScript 表达式通过括号嵌入到 JSX 语句中。
+
+自定义的组件也可以使用`props`。通过在不同的场景使用不同的属性定制,可以尽量提高自定义组件的复用范畴。只需在函数中引用`props`,然后按需处理即可。下面是一个例子:
+
+
+
+
+```SnackPlayer name=Props&ext=js
+import React from 'react';
+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 GreetingProps = {
+ name: string;
+};
+
+const Greeting = (props: GreetingProps) => {
+ return (
+
+ Hello {props.name}!
+
+ );
+};
+
+const LotsOfGreetings = () => {
+ return (
+
+
+
+
+
+ );
+};
+
+export default LotsOfGreetings;
+```
+
+
+
+
+我们在`Greeting`组件中将`name`作为一个属性来定制,这样可以复用这一组件来制作各种不同的"问候语"。上面的例子把`Greeting`组件写在 JSX 语句中,用法和[核心组件](intro-react-native-components)并无二致——这正是 React 体系的魅力所在——如果你想搭建一套自己的基础 UI 框架,那就放手做吧!
+
+上面的例子出现了一样新的名为[`View`](view.md)的组件。[`View`](view.md) 常用作其他组件的容器,来帮助控制布局和样式。
+
+仅仅使用`props`和基础的[`Text`](text.md)、[`Image`](image.md)以及[`View`](view.md)组件,你就已经足以编写各式各样的 UI 组件了。要学习如何动态修改你的界面,那就需要进一步[学习 State(状态)的概念](state.md)。
diff --git a/cnwebsite/versioned_docs/version-0.85/publishing-to-app-store.md b/cnwebsite/versioned_docs/version-0.85/publishing-to-app-store.md
new file mode 100644
index 00000000000..71e70c34bda
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/publishing-to-app-store.md
@@ -0,0 +1,59 @@
+---
+id: publishing-to-app-store
+title: 上架 App Store
+---
+
+上架应用的过程和任何其它原生 iOS 应用一样,但有一些额外的注意事项要考虑。
+
+:::info
+如果你正在使用 Expo,请阅读 Expo 的 [Deploying to App Stores](https://docs.expo.dev/distribution/app-stores/) 指南来构建和提交你的 app 到 Apple App Store。本指南适用于任何 React Native app,可以自动化部署过程。
+:::
+
+### 1. 配置 release scheme
+
+需要在 Xcode 使用`Release` scheme 编译在 App Store 发布的 app。`Release`版本的应用会自动禁用开发者菜单,同时也会将 js 文件和静态图片打包压缩后内置到包中,这样应用可以在本地读取而无需访问开发服务器(同时这样一来你也无法再调试,需要调试请将 Build Configuration 再改为 debug)。
+
+要配置 app 为使用`Release` scheme 编译,请前往**Product** → **Scheme** → **Edit Scheme**。选择侧边栏的**Run**标签,然后设置下拉的 Build Configuration 为`Release`。
+
+
+
+#### 优化技巧
+
+静态包在每次你目标物理设备时都会生成,即使在 Debug 模式下也是如此。如果你想节省时间,可以通过在 Xcode Build Phase `Bundle React Native code and images` 的 shell 脚本中添加以下内容来在 Debug 模式下关闭包生成:
+
+```shell
+ if [ "${CONFIGURATION}" == "Debug" ]; then
+ export SKIP_BUNDLING=true
+ fi
+```
+
+### 2. 编译发布 app
+
+现在可以通过点击Cmd ⌘ + B 或从菜单栏选择 **Product** → **Build** 编译发布 app。一旦编译发布,就能够向 beta 测试者发布 app,提交 app 到 App Store。
+
+:::info
+你也可以使用 `React Native CLI` 通过 `--mode` 选项(值为 `Release`,例如从项目根目录执行:`npm run ios -- --mode="Release"` 或 `yarn ios --mode Release`)来执行此操作。
+:::
+
+当你完成测试并准备好发布到 App Store 时,请按照以下指南操作。
+
+- 启动终端,导航到你 app 的 iOS 文件夹,输入 `open .`。
+- 双击 YOUR_APP_NAME.xcworkspace。它应该会启动 Xcode。
+- 点击 `Product` → `Archive`。确保将设备设置为 "Any iOS Device (arm64)"。
+
+:::note
+检查你的 Bundle Identifier,确保它与你在 Apple Developer Dashboard 的 Identifiers 中创建的完全一致。
+:::
+
+- 归档完成后,在归档窗口中点击 `Distribute App`。
+- 点击 `App Store Connect`(如果你想发布到 App Store)。
+- 点击 `Upload` → 确保所有复选框都已选中,点击 `Next`。
+- 根据需要选择 `Automatically manage signing` 或 `Manually manage signing`。
+- 点击 `Upload`。
+- 现在你可以在 App Store Connect 的 TestFlight 中找到它。
+
+现在填写必要的信息,在 Build 部分,选择 app 的 build,然后点击 `Save` → `Submit For Review`。
+
+### 3. 截图
+
+Apple Store 要求你提供最新设备的截图。可以在[这里](https://developer.apple.com/help/app-store-connect/reference/screenshot-specifications/)找到相关设备的参考。请注意,如果为其他尺寸提供了截图,则某些显示尺寸的截图不是必需的。
diff --git a/cnwebsite/versioned_docs/version-0.85/pushnotificationios.md b/cnwebsite/versioned_docs/version-0.85/pushnotificationios.md
new file mode 100644
index 00000000000..76c8b82b07f
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/pushnotificationios.md
@@ -0,0 +1,530 @@
+---
+id: pushnotificationios
+title: '🗑️ PushNotificationIOS'
+---
+
+:::warning 已弃用
+请改用[社区提供的替代方案](https://reactnative.directory/?search=notification)。
+:::
+
+
+
仅限原生代码项目
+
以下内容仅适用于暴露了原生代码的项目。如果你使用的是 Expo 托管工作流,请参阅 Expo 文档中的 Notifications 指南以获取相应的替代方案。
+
+
+处理应用的通知,包括通知调度和权限管理。
+
+---
+
+## 入门指南
+
+要启用推送通知,请先[在 Apple 配置你的通知](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server)以及服务端系统。
+
+然后,在项目中[启用远程通知](https://developer.apple.com/documentation/usernotifications/setting_up_a_remote_notification_server/pushing_background_updates_to_your_app#2980038)。这将自动启用所需的设置。
+
+### 启用 `register` 事件支持
+
+在你的 `AppDelegate.m` 中添加:
+
+```objectivec
+#import
+```
+
+然后实现以下代码来处理远程通知注册事件:
+
+```objectivec
+- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
+{
+ // This will trigger 'register' events on PushNotificationIOS
+ [RCTPushNotificationManager didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
+}
+- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error
+{
+ // This will trigger 'registrationError' events on PushNotificationIOS
+ [RCTPushNotificationManager didFailToRegisterForRemoteNotificationsWithError:error];
+}
+```
+
+### 处理通知
+
+你需要在 `AppDelegate` 中实现 `UNUserNotificationCenterDelegate`:
+
+```objectivec
+#import
+
+@interface YourAppDelegate ()
+@end
+```
+
+在应用启动时设置代理:
+
+```objectivec
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+ ...
+ UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
+ center.delegate = self;
+
+ return YES;
+}
+```
+
+#### 前台通知
+
+实现 `userNotificationCenter:willPresentNotification:withCompletionHandler:` 来处理应用在前台时到达的通知。使用 completionHandler 来决定是否向用户显示通知,并相应地通知 `RCTPushNotificationManager`:
+
+```objectivec
+// Called when a notification is delivered to a foreground app.
+- (void)userNotificationCenter:(UNUserNotificationCenter *)center
+ willPresentNotification:(UNNotification *)notification
+ withCompletionHandler:(void (^)(UNNotificationPresentationOptions options))completionHandler
+{
+ // This will trigger 'notification' and 'localNotification' events on PushNotificationIOS
+ [RCTPushNotificationManager didReceiveNotification:notification];
+ // Decide if and how the notification will be shown to the user
+ completionHandler(UNNotificationPresentationOptionNone);
+}
+```
+
+#### 后台通知
+
+实现 `userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:` 来处理用户点击通知的情况,通常用于用户点击后台通知打开应用的场景。但是,如果你在 `userNotificationCenter:willPresentNotification:withCompletionHandler:` 中设置了显示前台通知,当用户点击前台通知时也会调用此方法。在这种情况下,你应该只在其中一个回调中通知 `RCTPushNotificationManager`。
+
+如果点击通知导致了应用启动,请调用 `setInitialNotification:`。如果通知之前没有被 `userNotificationCenter:willPresentNotification:withCompletionHandler:` 处理,还需要调用 `didReceiveNotification:`:
+
+```objectivec
+- (void) userNotificationCenter:(UNUserNotificationCenter *)center
+ didReceiveNotificationResponse:(UNNotificationResponse *)response
+ withCompletionHandler:(void (^)(void))completionHandler
+{
+ // This condition passes if the notification was tapped to launch the app
+ if ([response.actionIdentifier isEqualToString:UNNotificationDefaultActionIdentifier]) {
+ // Allow the notification to be retrieved on the JS side using getInitialNotification()
+ [RCTPushNotificationManager setInitialNotification:response.notification];
+ }
+ // This will trigger 'notification' and 'localNotification' events on PushNotificationIOS
+ [RCTPushNotificationManager didReceiveNotification:response.notification];
+ completionHandler();
+}
+```
+
+---
+
+# 参考文档
+
+## 方法
+
+### `presentLocalNotification()`
+
+```tsx
+static presentLocalNotification(details: PresentLocalNotificationDetails);
+```
+
+调度一个本地通知以立即展示。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ------- | ------ | ---- | ---------- |
+| details | object | 是 | 见下方说明 |
+
+`details` 是一个包含以下字段的对象:
+
+- `alertTitle`:作为通知提醒标题显示的文本。
+- `alertBody`:通知提醒中显示的消息。
+- `userInfo`:包含额外通知数据的对象(可选)。
+- `category`:此通知的类别,可操作通知必需(可选)。例如带有回复或点赞等额外操作的通知。
+- `applicationIconBadgeNumber`:作为应用图标角标显示的数字。此属性的默认值为 0,表示不显示角标(可选)。
+- `isSilent`:如果为 true,通知将不带声音(可选)。
+- `soundName`:通知触发时播放的声音(可选)。
+- `alertAction`:已弃用。这曾用于 iOS 旧版的 UILocalNotification。
+
+---
+
+### `scheduleLocalNotification()`
+
+```tsx
+static scheduleLocalNotification(details: ScheduleLocalNotificationDetails);
+```
+
+调度一个本地通知以在未来展示。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ------- | ------ | ---- | ---------- |
+| details | object | 是 | 见下方说明 |
+
+`details` 是一个包含以下字段的对象:
+
+- `alertTitle`:作为通知提醒标题显示的文本。
+- `alertBody`:通知提醒中显示的消息。
+- `fireDate`:通知触发的时间。使用 `fireDate` 或 `fireIntervalSeconds` 来调度通知,`fireDate` 优先。
+- `fireIntervalSeconds`:从现在起多少秒后显示通知。
+- `userInfo`:包含额外通知数据的对象(可选)。
+- `category`:此通知的类别,可操作通知必需(可选)。例如带有回复或点赞等额外操作的通知。
+- `applicationIconBadgeNumber`:作为应用图标角标显示的数字。此属性的默认值为 0,表示不显示角标(可选)。
+- `isSilent`:如果为 true,通知将不带声音(可选)。
+- `soundName`:通知触发时播放的声音(可选)。
+- `alertAction`:已弃用。这曾用于 iOS 旧版的 UILocalNotification。
+- `repeatInterval`:已弃用。请改用 `fireDate` 或 `fireIntervalSeconds`。
+
+---
+
+### `cancelAllLocalNotifications()`
+
+```tsx
+static cancelAllLocalNotifications();
+```
+
+取消所有已调度的本地通知。
+
+---
+
+### `removeAllDeliveredNotifications()`
+
+```tsx
+static removeAllDeliveredNotifications();
+```
+
+从通知中心移除所有已送达的通知。
+
+---
+
+### `getDeliveredNotifications()`
+
+```tsx
+static getDeliveredNotifications(callback: (notifications: Object[]) => void);
+```
+
+获取当前显示在通知中心的应用通知列表。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| -------- | -------- | ---- | -------------------------- |
+| callback | function | 是 | 接收已送达通知数组的函数。 |
+
+一个已送达的通知是包含以下字段的对象:
+
+- `identifier`:此通知的标识符。
+- `title`:此通知的标题。
+- `body`:此通知的正文。
+- `category`:此通知的类别(可选)。
+- `userInfo`:包含额外通知数据的对象(可选)。
+- `thread-id`:此通知的线程标识符(如果有的话)。
+
+---
+
+### `removeDeliveredNotifications()`
+
+```tsx
+static removeDeliveredNotifications(identifiers: string[]);
+```
+
+从通知中心移除指定的通知。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ----------- | ----- | ---- | ---------------- |
+| identifiers | array | 是 | 通知标识符数组。 |
+
+---
+
+### `setApplicationIconBadgeNumber()`
+
+```tsx
+static setApplicationIconBadgeNumber(num: number);
+```
+
+设置主屏幕上应用图标的角标数字。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ------ | ------ | ---- | ------------------ |
+| number | number | 是 | 应用图标的角标数字 |
+
+---
+
+### `getApplicationIconBadgeNumber()`
+
+```tsx
+static getApplicationIconBadgeNumber(callback: (num: number) => void);
+```
+
+获取主屏幕上应用图标当前的角标数字。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| -------- | -------- | ---- | ------------------------ |
+| callback | function | 是 | 处理当前角标数字的函数。 |
+
+---
+
+### `cancelLocalNotifications()`
+
+```tsx
+static cancelLocalNotifications(userInfo: Object);
+```
+
+取消与提供的 `userInfo` 中的字段匹配的所有已调度本地通知。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| -------- | ------ | ---- | ---- |
+| userInfo | object | 否 | |
+
+---
+
+### `getScheduledLocalNotifications()`
+
+```tsx
+static getScheduledLocalNotifications(
+ callback: (notifications: ScheduleLocalNotificationDetails[]) => void,
+);
+```
+
+获取当前已调度的本地通知列表。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| -------- | -------- | ---- | ---------------------------------- |
+| callback | function | 是 | 处理描述本地通知的对象数组的函数。 |
+
+---
+
+### `addEventListener()`
+
+```tsx
+static addEventListener(
+ type: PushNotificationEventName,
+ handler:
+ | ((notification: PushNotification) => void)
+ | ((deviceToken: string) => void)
+ | ((error: {message: string; code: number; details: any}) => void),
+);
+```
+
+为通知事件绑定监听器,包括本地通知、远程通知和通知注册结果。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ------- | -------- | ---- | ------------------------------ |
+| type | string | 是 | 要监听的事件类型。见下方说明。 |
+| handler | function | 是 | 监听器。 |
+
+有效的事件类型包括:
+
+- `notification`:收到远程通知时触发。处理函数会接收一个 `PushNotificationIOS` 实例。这会处理在前台到达的通知以及用户点击后从后台打开应用的通知。
+- `localNotification`:收到本地通知时触发。处理函数会接收一个 `PushNotificationIOS` 实例。这会处理在前台到达的通知以及用户点击后从后台打开应用的通知。
+- `register`:用户成功注册远程通知时触发。处理函数会接收一个表示 deviceToken 的十六进制字符串。
+- `registrationError`:用户注册远程通知失败时触发。通常由于 APNS 问题或设备是模拟器。处理函数会接收 `{message: string, code: number, details: any}`。
+
+---
+
+### `removeEventListener()`
+
+```tsx
+static removeEventListener(
+ type: PushNotificationEventName,
+);
+```
+
+移除事件监听器。在 `componentWillUnmount` 中执行此操作以防止内存泄漏。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ---- | ------ | ---- | ------------------------------------------- |
+| type | string | 是 | 事件类型。可选值参见 `addEventListener()`。 |
+
+---
+
+### `requestPermissions()`
+
+```tsx
+static requestPermissions(permissions?: PushNotificationPermissions[]);
+```
+
+向 iOS 请求通知权限,会弹出对话框提示用户。默认情况下会请求所有通知权限,但你可以选择性地指定要请求的权限。支持以下权限:
+
+- `alert`
+- `badge`
+- `sound`
+
+如果传入了一个映射对象,则只会请求值为真的权限。
+
+此方法返回一个 Promise,在用户接受或拒绝请求后、或者权限之前已被拒绝时解析。Promise 解析为请求完成后的权限状态。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ----------- | ----- | ---- | --------------------- |
+| permissions | array | 否 | alert、badge 或 sound |
+
+---
+
+### `abandonPermissions()`
+
+```tsx
+static abandonPermissions();
+```
+
+取消注册通过 Apple Push Notification service 接收的所有远程通知。
+
+你应该只在极少数情况下调用此方法,例如当新版本的应用不再支持所有类型的远程通知时。用户可以通过"设置"应用临时阻止应用接收远程通知。通过此方法取消注册的应用始终可以重新注册。
+
+---
+
+### `checkPermissions()`
+
+```tsx
+static checkPermissions(
+ callback: (permissions: PushNotificationPermissions) => void,
+);
+```
+
+检查当前启用了哪些推送权限。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| -------- | -------- | ---- | ---------- |
+| callback | function | 是 | 见下方说明 |
+
+`callback` 会接收一个 `permissions` 对象:
+
+- `alert: boolean`
+- `badge: boolean`
+- `sound: boolean`
+
+---
+
+### `getInitialNotification()`
+
+```tsx
+static getInitialNotification(): Promise;
+```
+
+此方法返回一个 Promise。如果应用是通过推送通知启动的,Promise 会解析为一个 `PushNotificationIOS` 类型的对象,对应被点击的通知。否则解析为 `null`。
+
+---
+
+### `getAuthorizationStatus()`
+
+```tsx
+static getAuthorizationStatus(): Promise;
+```
+
+此方法返回一个 Promise,解析为当前的通知授权状态。可能的值请参见 [UNAuthorizationStatus](https://developer.apple.com/documentation/usernotifications/unauthorizationstatus?language=objc)。
+
+---
+
+### `finish()`
+
+```tsx
+finish(result: string);
+```
+
+此方法适用于通过 [`application:didReceiveRemoteNotification:fetchCompletionHandler:`](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application?language=objc) 接收的远程通知。但是,此方法已被 `UNUserNotificationCenterDelegate` 取代,如果同时实现了 `application:didReceiveRemoteNotification:fetchCompletionHandler:` 和 `UNUserNotificationCenterDelegate` 的较新处理方法,则不会再调用此方法。
+
+如果你仍然依赖 `application:didReceiveRemoteNotification:fetchCompletionHandler:`,需要在 iOS 端设置事件处理:
+
+```objectivec
+- (void) application:(UIApplication *)application
+ didReceiveRemoteNotification:(NSDictionary *)userInfo
+ fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))handler
+{
+ [RCTPushNotificationManager didReceiveRemoteNotification:userInfo fetchCompletionHandler:handler];
+}
+```
+
+在 JS 端完成通知处理后,调用 `finish()` 来执行原生完成处理器。调用此方法时,传入最能描述操作结果的获取结果值。可能的值列表请参见 `PushNotificationIOS.FetchResult`。
+
+如果你使用了 `application:didReceiveRemoteNotification:fetchCompletionHandler:`,你*必须*调用此处理器,并且应尽快调用。更多详情请参阅[官方文档](https://developer.apple.com/documentation/uikit/uiapplicationdelegate/1623013-application?language=objc)。
+
+---
+
+### `getMessage()`
+
+```tsx
+getMessage(): string | Object;
+```
+
+`getAlert` 的别名,用于获取通知的主消息字符串。
+
+---
+
+### `getSound()`
+
+```tsx
+getSound(): string;
+```
+
+从 `aps` 对象中获取声音字符串。对于本地通知,此值为 `null`。
+
+---
+
+### `getCategory()`
+
+```tsx
+getCategory(): string;
+```
+
+从 `aps` 对象中获取类别字符串。
+
+---
+
+### `getAlert()`
+
+```tsx
+getAlert(): string | Object;
+```
+
+从 `aps` 对象中获取通知的主消息。另见别名:`getMessage()`。
+
+---
+
+### `getContentAvailable()`
+
+```tsx
+getContentAvailable(): number;
+```
+
+从 `aps` 对象中获取 content-available 数值。
+
+---
+
+### `getBadgeCount()`
+
+```tsx
+getBadgeCount(): number;
+```
+
+从 `aps` 对象中获取角标计数数值。
+
+---
+
+### `getData()`
+
+```tsx
+getData(): Object;
+```
+
+获取通知上的数据对象。
+
+---
+
+### `getThreadID()`
+
+```tsx
+getThreadID();
+```
+
+获取通知上的线程 ID。
diff --git a/cnwebsite/versioned_docs/version-0.85/ram-bundles-inline-requires.md b/cnwebsite/versioned_docs/version-0.85/ram-bundles-inline-requires.md
new file mode 100644
index 00000000000..aa5446d1404
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/ram-bundles-inline-requires.md
@@ -0,0 +1,180 @@
+---
+id: ram-bundles-inline-requires
+title: RAM Bundles 和内联引用优化
+---
+
+如果你有一个较为庞大的应用程序,你可能要考虑使用`RAM`(Random Access Modules,随机存取模块)格式的 bundle 和内联引用。这对于具有大量页面的应用程序是非常有用的,这些页面在应用程序的典型使用过程中可能不会被打开。通常对于启动后一段时间内不需要大量代码的应用程序来说是非常有用的。例如应用程序包含复杂的配置文件屏幕或较少使用的功能,但大多数会话只涉及访问应用程序的主屏幕更新。我们可以通过使用`RAM`格式来优化`bundle`的加载,并且内联引用这些功能和页面(当它们被实际使用时)。
+
+### 加载 JavaScript
+
+在 react-native 执行 JS 代码之前,必须将代码加载到内存中并进行解析。如果你加载了一个 50MB 的 bundle,那么所有的 50mb 都必须被加载和解析才能被执行。RAM 格式的 bundle 则对此进行了优化,即启动时只加载 50MB 中实际需要的部分,之后再逐渐按需加载更多的包。
+
+### 内联引用
+
+内联引用(require 代替 import)可以延迟模块或文件的加载,直到实际需要该文件。一个基本的例子看起来像这样:
+
+#### 优化前
+
+```
+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
+console.log('VeryExpensive component loaded');
+
+export default class VeryExpensive extends Component {
+ // lots and lots of code
+ render() {
+ return Very Expensive Component ;
+ }
+}
+```
+
+#### 优化后
+
+```
+import React, { Component } from 'react';
+import { TouchableOpacity, View, Text } from 'react-native';
+
+let VeryExpensive = null;
+
+export default class Optimized extends Component {
+ state = { needsExpensive: false };
+
+ didPress = () => {
+ if (VeryExpensive == null) {
+ VeryExpensive = require('./VeryExpensive').default;
+ }
+
+ this.setState(() => ({
+ needsExpensive: true,
+ }));
+ };
+
+ render() {
+ return (
+
+
+ Load
+
+ {this.state.needsExpensive ? : null}
+
+ );
+ }
+}
+```
+
+即便不使用 RAM 格式,内联引用也会使启动时间减少,因为优化后的代码只有在第一次 require 时才会执行。
+
+### 启用 RAM 格式
+
+在 iOS 上使用 RAM 格式将创建一个简单的索引文件,React Native 将根据此文件一次加载一个模块。在 Android 上,默认情况下它会为每个模块创建一组文件。你可以像 iOS 一样,强制 Android 只创建一个文件,但使用多个文件可以提高性能,并降低内存占用。
+
+在 Xcode 中启用 RAM 格式,需要编辑 build phase 里的"Bundle React Native code and images"。在`../node_modules/react-native/scripts/react-native-xcode.sh`中添加 `export BUNDLE_COMMAND="ram-bundle"`:
+
+```
+export BUNDLE_COMMAND="ram-bundle"
+export NODE_BINARY=node
+../node_modules/react-native/scripts/react-native-xcode.sh
+```
+
+在 Android 上启用 RAM 格式,需要编辑 android/app/build.gradle 文件。在`apply from: "../../node_modules/react-native/react.gradle"`之前修改或添加`project.ext.react`:
+
+```
+project.ext.react = [
+ bundleCommand: "ram-bundle",
+]
+```
+
+如果在 Android 上,你想使用单个索引文件(如前所述),请在 Android 上使用以下行:
+
+```
+project.ext.react = [
+ bundleCommand: "ram-bundle",
+ extraPackagerArgs: ["--indexed-ram-bundle"]
+]
+```
+
+> **_Note_**: If you are using [Hermes JS Engine](https://github.com/facebook/hermes), you do not need RAM bundles. When loading the bytecode, `mmap` ensures that the entire file is not loaded.
+
+### 配置预加载及内联引用
+
+现在我们已经启用了RAM格式,然而调用`require`会造成额外的开销。因为当遇到尚未加载的模块时,`require`需要通过bridge来发送消息。这主要会影响到启动速度,因为在应用程序加载初始模块时可能触发相当大量的请求调用。幸运的是,我们可以配置一部分模块进行预加载。为了做到这一点,你将需要实现某种形式的内联引用。
+
+### 调试预加载的模块
+
+在您的根文件 (index.(ios|android).js) 中,您可以在初始导入(initial imports)之后添加以下内容:
+
+```
+const modules = require.getModules();
+const moduleIds = Object.keys(modules);
+const loadedModuleNames = moduleIds
+ .filter(moduleId => modules[moduleId].isInitialized)
+ .map(moduleId => modules[moduleId].verboseName);
+const waitingModuleNames = moduleIds
+ .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
+);
+
+// grab this text blob, and put it in a file named packager/modulePaths.js
+console.log(`module.exports = ${JSON.stringify(loadedModuleNames.sort())};`);
+```
+
+当你运行你的应用程序时,你可以查看 console 控制台,有多少模块已经加载,有多少模块在等待。你可能想查看 moduleNames,看看是否有任何意外。注意在首次 import 时调用的内联引用。你可能需要检查和重构,以确保只有你想要的模块在启动时加载。请注意,您可以根据需要修改 Systrace 对象,以帮助调试有问题的引用。
+
+```
+require.Systrace.beginEvent = (message) => {
+ if(message.includes(problematicModule)) {
+ throw new Error();
+ }
+}
+```
+
+虽然每个 App 各有不同,但只加载第一个页面所需的模块是有普适意义的。当你满意时,把 loadedModuleNames 的输出放到 packager/modulePaths.js 文件中。
+
+### 更新配置文件(metro.config.js)
+
+我们现在需要更新项目根目录中的`metro.config.js`以使用新生成的`modulePaths.js`文件:
+
+```
+const modulePaths = require('./packager/modulePaths');
+const resolve = require('path').resolve;
+const fs = require('fs');
+
+// Update the following line if the root folder of your app is somewhere else.
+const ROOT_FOLDER = resolve(__dirname, '..');
+
+const config = {
+ transformer: {
+ getTransformOptions: () => {
+ const moduleMap = {};
+ modulePaths.forEach(path => {
+ if (fs.existsSync(path)) {
+ moduleMap[resolve(path)] = true;
+ }
+ });
+ return {
+ preloadedModules: moduleMap,
+ transform: { inlineRequires: { blacklist: moduleMap } },
+ };
+ },
+ },
+ projectRoot: ROOT_FOLDER,
+};
+
+module.exports = config;
+```
+
+在启用RAM格式之后,配置文件中的`preloadedModules`条目指示哪些模块需要预加载。当 bundle 被加载时,这些模块立即被加载,甚至在任何 requires 执行之前。blacklist 表明这些模块不应该被要求内联引用,因为它们是预加载的,所以使用内联没有性能优势。实际上每次解析内联引用 JavaScript 都会花费额外的时间。
+
+### 测试和衡量改进
+
+您现在应该准备好使用RAM格式和内联引用来构建您的应用了。保存启动前后的时间,来测试下有多少改进吧!
diff --git a/cnwebsite/versioned_docs/version-0.85/react-native-devtools.md b/cnwebsite/versioned_docs/version-0.85/react-native-devtools.md
new file mode 100644
index 00000000000..b1e1cd9b8e8
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/react-native-devtools.md
@@ -0,0 +1,214 @@
+---
+id: react-native-devtools
+title: React Native DevTools
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+React Native DevTools 是我们为 React Native 打造的现代调试体验。它从零开始专门构建,旨在比以前的调试方法更加集成、准确和可靠。
+
+
+
+React Native DevTools 旨在调试 React 应用层面的问题,而不是取代原生工具。如果你需要检查 React Native 的底层平台层(例如,在开发原生模块时),请使用 Android Studio 和 Xcode 中可用的调试工具(请参阅[调试原生代码](/docs/debugging-native-code))。
+
+
+**💡 兼容性** — 在 0.76 中发布
+
+React Native DevTools 支持所有运行 Hermes 的 React Native 应用。它取代了以前的 Flipper、实验性调试器和 Hermes 调试器(Chrome)前端。
+
+无法在任何旧版本的 React Native 上使用 React Native DevTools。
+
+- **Chrome Browser DevTools — 不再支持**
+ - 通过 `chrome://inspect` 连接到 React Native 不再受支持。由于最新版本的 Chrome DevTools(构建用于匹配最新浏览器功能和 API)未经过测试,并且此前端缺少我们的定制内容,因此功能可能无法正常工作。我们会随 React Native DevTools 一起提供受支持的版本。
+- **Visual Studio Code — 不再支持**(已有限制)
+ - 第三方扩展如 [Expo Tools](https://github.com/expo/vscode-expo) 和 [Radon IDE](https://ide.swmansion.com/) 可能具有改进的兼容性,但不受 React 团队的直接支持。
+
+
+
+**💡 反馈和常见问题**
+
+我们希望你在所有平台上用来调试 React 的工具是可靠的、熟悉的、简单的和一致的。本页描述的所有功能都是基于这些原则构建的,我们还计划在未来提供更多能力。
+
+我们正在积极迭代 React Native DevTools 的未来,并创建了一个集中的 [GitHub 讨论](https://github.com/react-native-community/discussions-and-proposals/discussions/819)来跟踪问题、常见问题和反馈。
+
+
+
+## 核心功能
+
+React Native DevTools 基于 Chrome DevTools 前端。如果你有 Web 开发背景,其功能应该很熟悉。作为起点,我们建议浏览 [Chrome DevTools 文档](https://developer.chrome.com/docs/devtools),其中包含完整的指南以及视频资源。
+
+### Console
+
+
+
+Console 面板允许你查看和过滤消息、执行 JavaScript、检查对象属性等。
+
+[Console 功能参考 | Chrome DevTools](https://developer.chrome.com/docs/devtools/console/reference)
+
+#### 实用提示
+
+- 如果你的应用有很多日志,请使用过滤框或更改显示的日志级别。
+- 使用 [Live Expressions](https://developer.chrome.com/docs/devtools/console/live-expressions) 实时观察值的变化。
+- 使用 [Preserve Logs](https://developer.chrome.com/docs/devtools/console/reference#persist) 在重新加载后保持消息。
+- 使用 Ctrl + L 清除控制台视图。
+
+### Sources 和断点
+
+
+
+Sources 面板允许你查看应用的源文件并注册断点。使用断点定义一行代码,让应用在此暂停——允许你检查程序的实时状态并逐步执行代码。
+
+[使用断点暂停代码 | Chrome DevTools](https://developer.chrome.com/docs/devtools/javascript/breakpoints)
+
+:::tip
+
+#### 迷你指南
+
+断点是你调试工具箱中的基础工具!
+
+1. 使用侧边栏或 Cmd ⌘ +P / Ctrl +P 导航到源文件。
+2. 点击代码行旁边的行号列以添加断点。
+3. 暂停时使用右上角的导航控件[逐步执行代码](https://developer.chrome.com/docs/devtools/javascript/reference#stepping)。
+
+:::
+
+#### 实用提示
+
+- 当应用暂停时,会出现"Paused in Debugger"覆盖层。点击它即可恢复。
+- 注意断点处的右侧面板,它允许你检查当前作用域和调用栈,并设置监视表达式。
+- 使用 `debugger;` 语句可以从文本编辑器快速设置断点。它会通过 Fast Refresh 立即到达设备。
+- 有多种断点类型!例如,[条件断点和日志点](https://developer.chrome.com/docs/devtools/javascript/breakpoints#overview)。
+
+### Network 自 0.83 起
+
+
+
+Network 面板允许你查看和检查应用发出的网络请求。记录的请求提供详细的元数据,如时间信息和发送/接收的请求头,以及响应预览。
+
+打开 DevTools 时网络请求会自动记录。我们支持 Chrome 的大部分功能,但有一些例外。详见下文。
+
+
+💡 网络事件覆盖范围、Expo 支持
+
+**哪些网络事件会被捕获?**
+
+目前,我们记录所有通过 `fetch()`、`XMLHttpRequest` 和 `` 发起的网络调用——对自定义网络库(如 Expo Fetch)的支持将在后续添加。
+
+**Expo Network 差异**
+
+因此,使用 Expo 的应用将继续看到"Expo Network"面板——这是 Expo 框架的单独实现,它会记录这些额外的请求来源,但功能稍有减少。
+
+- 覆盖 Expo 特定的网络事件。
+- 不支持请求发起者信息。
+- 不集成 Performance 面板。
+
+我们正在与 Expo 合作,计划在未来版本中将 Expo Fetch 和第三方网络库集成到我们新的 Network 检查管道中。
+
+**尚未实现的功能**
+
+在发布时,以下功能在 React Native 中尚不支持:
+
+- WebSocket 事件
+- 网络响应模拟
+- 模拟网络限速
+
+
+
+
+💡 响应预览缓冲区大小
+
+如果你正在检查大量响应数据,请注意响应预览缓存在设备上的缓冲区中,最大大小为 100MB。这意味着如果缓存变得过大,我们可能会清除响应预览(但不会清除元数据),最旧的请求最先被清除。
+
+
+
+#### 实用提示
+
+- 使用 Initiator 标签页查看应用中网络请求发起的调用栈。
+- 网络事件也会显示在 Performance 面板的 Network 轨道中。
+
+### Performance 自 0.83 起
+
+
+
+性能追踪允许你在应用中录制性能会话,以了解 JavaScript 代码的运行情况以及哪些操作耗时最多。在 React Native 中,我们在单个性能时间线中展示 JavaScript 执行、React 性能轨道、网络事件和自定义 [User Timings](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/User_timing)。
+
+#### 实用提示
+
+- 使用[注释](https://developer.chrome.com/docs/devtools/performance/annotations)(Shift+拖拽)来标记性能追踪——在[下载和分享](https://developer.chrome.com/docs/devtools/performance/save-trace)追踪记录给同事之前非常有用。注释还提供了一种快速估算时间跨度(以**秒**为单位)的方式。
+- 使用应用中的 [`PerformanceObserver` API](./global-PerformanceObserver.md) 在运行时观察性能事件——如果你想捕获性能遥测数据,这非常有用。
+
+#### 了解更多
+
+- [React 性能轨道](https://react.dev/reference/dev-tools/react-performance-tracks)
+- [Performance API > User Timings | MDN](https://developer.mozilla.org/en-US/docs/Web/API/Performance_API/User_timing)
+- ["像高级开发者一样调试 — React Native Performance 面板" | Software Mansion](https://blog.swmansion.com/react-native-debugging-new-performance-panel-in-react-native-0-83-21ca90871f6d)
+
+### Memory
+
+
+
+Memory 面板允许你拍摄堆快照,并查看 JavaScript 代码随时间推移的内存使用情况。
+
+[录制堆快照 | Chrome DevTools](https://developer.chrome.com/docs/devtools/memory-problems/heap-snapshots)
+
+#### 实用提示
+
+- 使用 Cmd ⌘ +F / Ctrl +F 在堆中过滤特定对象。
+- 拍摄[分配时间线报告](https://developer.chrome.com/docs/devtools/memory-problems/allocation-profiler)可以以图形方式查看随时间推移的内存使用情况,有助于识别可能的内存泄漏。
+
+## React DevTools 功能
+
+在集成的 Components 和 Profiler 面板中,你可以找到 [React DevTools](https://react.dev/learn/react-developer-tools) 浏览器扩展的所有功能。它们在 React Native DevTools 中可以无缝使用。
+
+### React Components
+
+
+
+React Components 面板允许你检查和更新渲染的 React 组件树。
+
+- 在 DevTools 中悬停或选择元素,设备上的对应元素会被高亮显示。
+- 要在 DevTools 中定位元素,请点击左上角的"选择元素"按钮,然后点击应用中的任意元素。
+
+#### 实用提示
+
+- 可以使用右侧面板在运行时查看和修改组件的 props 和 state。
+- 使用 [React Compiler](https://react.dev/learn/react-compiler) 优化的组件会标注"Memo ✨"徽章。
+
+:::tip
+
+#### 进阶提示:高亮重新渲染
+
+重新渲染可能是 React 应用中性能问题的重要原因。DevTools 可以在组件重新渲染时实时高亮显示。
+
+- 要启用此功能,请点击 View Settings(`⚙︎`)图标,勾选"Highlight updates when components render"。
+
+
+
+:::
+
+### React Profiler
+
+
+
+React Profiler 面板允许你录制性能分析报告,以了解组件渲染和 React commit 的耗时情况。
+
+更多信息请参阅[原始的 2018 年指南](https://legacy.reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html#reading-performance-data)(注意部分内容可能已过时)。
+
+## 重新连接 DevTools
+
+有时 DevTools 可能会与目标设备断开连接。这可能发生在以下情况下:
+
+- 应用已关闭。
+- 应用已重新构建(安装了新的原生构建版本)。
+- 应用在原生侧崩溃。
+- 开发服务器(Metro)已退出。
+- 物理设备已断开连接。
+
+断开连接时,将显示一个消息为"Debugging connection was closed"的对话框。
+
+
+
+从这里,你可以:
+
+- **关闭**:选择关闭(`×`)图标或点击对话框外部,返回到断开连接前最后状态的 DevTools UI。
+- **重新连接**:选择"Reconnect DevTools",并解决断开连接的原因后重试。
diff --git a/cnwebsite/versioned_docs/version-0.85/react-native-gradle-plugin.md b/cnwebsite/versioned_docs/version-0.85/react-native-gradle-plugin.md
new file mode 100644
index 00000000000..969dcecd111
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/react-native-gradle-plugin.md
@@ -0,0 +1,190 @@
+---
+id: react-native-gradle-plugin
+title: React Native Gradle Plugin
+---
+
+本指南描述了如何配置 **React Native Gradle Plugin**(通常称为 RNGP)来为 Android 构建 React Native 应用。
+
+## 使用插件
+
+React Native Gradle Plugin 作为单独的 NPM 包分发,并随 `react-native` 自动安装。
+
+插件已为使用 `npx react-native init` 创建的新项目配置。如果你使用此命令创建应用,则不需要进行任何额外步骤来安装它。
+
+如果你正在将 React Native 集成到现有项目中,请参阅 [对应页面](/docs/next/integration-with-existing-apps#configuring-gradle):它包含有关如何安装插件的特定说明。
+
+## 配置插件
+
+默认情况下,插件会**开箱即用**,并使用合理的默认值。你应该参考本指南并仅在需要时自定义行为。
+
+要配置插件,可以修改 `android/app/build.gradle` 中的 `react` 块:
+
+```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.
+}
+```
+
+每个配置键的描述如下:
+
+### `root`
+
+这是你的 React Native 项目的根文件夹,即 `package.json` 文件所在的位置。默认是 `..`。你可以按如下方式自定义:
+
+```groovy
+root = file("../")
+```
+
+### `reactNativeDir`
+
+这是 `react-native` 包所在的文件夹。默认是 `../node_modules/react-native`。如果你在 Monorepo 中或在不同的包管理器中使用,可以调整 `reactNativeDir` 以适应你的设置。
+
+你可以按如下方式自定义:
+
+```groovy
+reactNativeDir = file("../node_modules/react-native")
+```
+
+### `codegenDir`
+
+这是 `react-native-codegen` 包所在的文件夹。默认是 `../node_modules/react-native-codegen`。如果你在 Monorepo 中或在不同的包管理器中使用,可以调整 `codegenDir` 以适应你的设置。
+
+你可以按如下方式自定义:
+
+```groovy
+codegenDir = file("../node_modules/@react-native/codegen")
+```
+
+### `cliFile`
+
+这是 React Native CLI 的入口文件。默认是 `../node_modules/react-native/cli.js`。入口文件是必需的,因为插件需要调用 CLI 来为应用生成捆绑包。
+
+如果你在 Monorepo 中或在不同的包管理器中使用,可以调整 `cliFile` 以适应你的设置。
+
+你可以按如下方式自定义:
+
+```groovy
+cliFile = file("../node_modules/react-native/cli.js")
+```
+
+### `debuggableVariants`
+
+这是可调试变体的列表(有关变体的更多上下文,请参阅 [使用变体](#using-variants))。
+
+默认情况下,插件仅将 `debug` 视为可调试变体,而 `release` 则不是。如果你有其他变体(如 `staging`、`lite` 等),则需要相应调整。
+
+列出的变体将不会带有已发布的捆绑包,因此你需要运行 Metro 来运行它们。
+
+你可以按如下方式自定义:
+
+```groovy
+debuggableVariants = ["liteDebug", "prodDebug"]
+```
+
+### `nodeExecutableAndArgs`
+
+这是用于所有脚本的 node 命令和参数的列表。默认是 `[node]`,但可以按如下方式自定义:
+
+```groovy
+nodeExecutableAndArgs = ["node"]
+```
+
+### `bundleCommand`
+
+这是用于创建应用捆绑包的 `bundle` 命令的名称。如果你使用 [RAM Bundles](/docs/ram-bundles-inline-requires),则此命令非常有用。默认是 `bundle`,但可以按如下方式自定义:
+
+```groovy
+bundleCommand = "ram-bundle"
+```
+
+### `bundleConfig`
+
+这是传递给 `bundle --config ` 的配置文件的路径。默认是空(不提供配置文件)。有关捆绑配置文件的更多信息,请参阅 [CLI 文档](https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle)。可以按如下方式自定义:
+
+```groovy
+bundleConfig = file(../rn-cli.config.js)
+```
+
+### `bundleAssetName`
+
+这是应该生成的捆绑包文件的名称。默认是 `index.android.bundle`。可以按如下方式自定义:
+
+```groovy
+bundleAssetName = "MyApplication.android.bundle"
+```
+
+### `entryFile`
+
+这是用于捆绑包生成的入口文件。默认是搜索 `index.android.js` 或 `index.js`。可以按如下方式自定义:
+
+```groovy
+entryFile = file("../js/MyApplication.android.js")
+```
+
+### `extraPackagerArgs`
+
+这是传递给 `bundle` 命令的额外标志的列表。可用标志的列表在 [CLI 文档](https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle) 中。默认是空。可以按如下方式自定义:
+
+```groovy
+extraPackagerArgs = []
+```
+
+### `hermesCommand`
+
+这是 `hermesc` 命令的路径(Hermes 编译器)。React Native 附带了一个 Hermes 编译器版本,因此你通常不需要自定义此项。插件将使用正确的编译器。
+
+### `hermesFlags`
+
+这是传递给 `hermesc` 的标志列表。默认是 `["-O", "-output-source-map"]`。可以按如下方式自定义:
+
+```groovy
+hermesFlags = ["-O", "-output-source-map"]
+```
+
+### `enableBundleCompression`
+
+Bundle 资源在打包到 `.apk` 中时是否应该被压缩。
+
+禁用 `.bundle` 的压缩允许它直接内存映射到 RAM,从而改善启动时间——代价是在磁盘上产生更大的应用大小。请注意,`.apk` 的下载大小基本不受影响,因为 `.apk` 文件在下载前会被压缩。
+
+默认情况下这是禁用的,你不应该启用它,除非你真的关心应用的磁盘空间。
+
+## 使用 Flavors 与 Build Variants
+
+在构建 Android 应用时,你可能希望使用 [自定义 Flavors](https://developer.android.com/studio/build/build-variants#product-flavors) 来从同一个项目中生成不同版本的 app。
+
+请参阅 [官方 Android 指南](https://developer.android.com/studio/build/build-variants) 来配置自定义构建类型(如 `staging`)或自定义 Flavors(如 `full`、`lite` 等)。默认情况下,新应用有两个构建类型(`debug` 和 `release`),没有自定义 Flavors。
+
+所有构建类型和 Flavors 的组合生成一组 **build variants**。例如,对于 `debug`/`staging`/`release` 构建类型和 `full`/`lite` Flavors,你将拥有 6 个 build variants:`fullDebug`、`fullStaging`、`fullRelease` 等等。
+
+如果你使用除了 `debug` 和 `release` 之外的自定义变体,你需要通过 [`debuggableVariants`](#debuggablevariants) 配置来指示插件哪些变体是 **可调试** 的,如下所示:
+
+```diff
+apply plugin: "com.facebook.react"
+
+react {
++ debuggableVariants = ["fullStaging", "fullDebug"]
+}
+```
+
+这是必要的,因为插件将跳过所有 `debuggableVariants` 的 JS 捆绑:你需要运行 Metro 来运行它们。例如,如果你在 `debuggableVariants` 中列出 `fullStaging`,则无法将其发布到商店,因为它将缺少捆绑包。
+
+## 插件在幕后做什么?
+
+React Native Gradle Plugin 负责配置你的应用构建,以将 React Native 应用发布到生产环境中。插件还用于在第三方库中运行用于新架构的 [Codegen](/docs/the-new-architecture/pillars-codegen)。
+
+以下是插件的责任总结:
+
+- 为每个非可调试变体添加一个 `createBundleJsAndAssets` 任务,负责调用 `bundle`、`hermesc` 和 `compose-source-map` 命令。
+- 设置 `com.facebook.react:react-android` 和 `com.facebook.react:hermes-android` 的适当版本,从 `react-native` 的 `package.json` 中读取 React Native 版本。
+- 设置适当的 Maven 仓库(Maven Central、Google Maven Repo、JSC 本地 Maven 仓库等),以使用所有必要的 Maven 依赖项。
+- 设置 NDK,以便你可以构建使用新架构的应用。
+- 设置 `buildConfigFields`,以便你可以在运行时知道是否启用了 Hermes 或新架构。
+- 设置 Metro DevServer 端口作为 Android 资源,以便应用知道连接到哪个端口。
+- 如果库或应用使用新架构的 Codegen,则调用 [React Native Codegen](/docs/the-new-architecture/pillars-codegen)。
diff --git a/cnwebsite/versioned_docs/version-0.85/react-node.md b/cnwebsite/versioned_docs/version-0.85/react-node.md
new file mode 100644
index 00000000000..5233a3b0822
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/react-node.md
@@ -0,0 +1,13 @@
+---
+id: react-node
+title: React 节点对象
+---
+
+React 节点对象有以下这些类型:
+
+- Boolean (实际渲染会被忽略)
+- `null` or `undefined` (实际渲染会被忽略)
+- Number
+- String
+- React 元素 (JSX 语句的返回值)
+- 由以上类型数据组成的数组(还可以嵌套)
diff --git a/cnwebsite/versioned_docs/version-0.85/rect.md b/cnwebsite/versioned_docs/version-0.85/rect.md
new file mode 100644
index 00000000000..de69502474a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/rect.md
@@ -0,0 +1,50 @@
+---
+id: rect
+title: 矩形区域对象
+---
+
+`Rect` 接受数值像素值来描述如何扩展矩形区域。这些值会被添加到原始区域的大小上以扩展它。
+
+## 示例
+
+```js
+{
+ bottom: 20,
+ left: null,
+ right: undefined,
+ top: 50
+}
+```
+
+## 属性与值
+
+### `bottom`
+
+| Type | Required |
+| --------------------------- | -------- |
+| number, `null`, `undefined` | No |
+
+### `left`
+
+| Type | Required |
+| --------------------------- | -------- |
+| number, `null`, `undefined` | No |
+
+### `right`
+
+| Type | Required |
+| --------------------------- | -------- |
+| number, `null`, `undefined` | No |
+
+### `top`
+
+| Type | Required |
+| --------------------------- | -------- |
+| number, `null`, `undefined` | No |
+
+## 被下列组件引用
+
+- [`Image`](image)
+- [`Pressable`](pressable)
+- [`Text`](text)
+- [`TouchableWithoutFeedback`](touchablewithoutfeedback)
diff --git a/cnwebsite/versioned_docs/version-0.85/refreshcontrol.md b/cnwebsite/versioned_docs/version-0.85/refreshcontrol.md
new file mode 100644
index 00000000000..0762021582a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/refreshcontrol.md
@@ -0,0 +1,170 @@
+---
+id: refreshcontrol
+title: RefreshControl
+---
+
+这一组件可以用在 ScrollView 或 FlatList 内部,为其添加下拉刷新的功能。当 ScrollView 处于竖直方向的起点位置(scrollY: 0),此时下拉会触发一个`onRefresh`事件。
+
+## 示例
+
+```SnackPlayer name=RefreshControl&supportedPlatforms=ios,android
+import React from 'react';
+import {
+ ScrollView,
+ RefreshControl,
+ StyleSheet,
+ Text,
+ SafeAreaView,
+} from 'react-native';
+import Constants from 'expo-constants';
+
+const wait = (timeout) => {
+ return new Promise(resolve => {
+ setTimeout(resolve, timeout);
+ });
+}
+
+const App = () => {
+ const [refreshing, setRefreshing] = React.useState(false);
+
+ const onRefresh = React.useCallback(() => {
+ setRefreshing(true);
+
+ wait(2000).then(() => setRefreshing(false));
+ }, []);
+
+ return (
+
+
+ }
+ >
+ Pull down to see RefreshControl indicator
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ marginTop: Constants.statusBarHeight,
+ },
+ scrollView: {
+ flex: 1,
+ backgroundColor: 'pink',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
+
+export default App;
+```
+
+**注意:** `refreshing`是一个受控属性, 所以必须在`onRefresh`函数中设置为 true,否则 loading 指示器会立即停止。
+
+---
+
+# 文档
+
+## Props
+
+### `refreshing`
+
+视图是否应该在刷新时显示指示器。
+
+| 类型 | 必需 |
+| ---- | ---- |
+| bool | 是 |
+
+---
+
+### `onRefresh`
+
+在视图开始刷新时调用。
+
+| 类型 | 必需 |
+| -------- | ---- |
+| function | 否 |
+
+---
+
+### `colors`
+
+指定至少一种颜色用来绘制刷新指示器。
+
+| 类型 | 必需 | 平台 |
+| --------------------------- | ---- | ------- |
+| array of [color](colors.md) | 否 | Android |
+
+---
+
+### `enabled`
+
+指定是否要启用刷新指示器。
+
+| 类型 | 必需 | 平台 |
+| ---- | ---- | ------- |
+| bool | 否 | Android |
+
+---
+
+### `progressBackgroundColor`
+
+指定刷新指示器的背景色。
+
+| 类型 | 必需 | 平台 |
+| ------------------ | ---- | ------- |
+| [color](colors.md) | 否 | Android |
+
+---
+
+### `progressViewOffset`
+
+指定刷新指示器的垂直起始位置(top offset)。
+
+| 类型 | 必需 | 平台 |
+| ------ | ---- | ------- |
+| number | 否 | Android |
+
+---
+
+### `size`
+
+指定刷新指示器的大小,具体数值可参阅 RefreshControl.SIZE.
+
+| 类型 | 必需 | 平台 |
+| ---------------------------------------------------------------------- | ---- | ------- |
+| enum(RefreshLayoutConsts.SIZE.DEFAULT, RefreshLayoutConsts.SIZE.LARGE) | 否 | Android |
+
+---
+
+### `tintColor`
+
+指定刷新指示器的颜色。
+
+| 类型 | 必需 | 平台 |
+| ------------------ | ---- | ---- |
+| [color](colors.md) | 否 | iOS |
+
+---
+
+### `title`
+
+指定刷新指示器下显示的文字。
+
+| 类型 | 必需 | 平台 |
+| ------ | ---- | ---- |
+| string | 否 | iOS |
+
+---
+
+### `titleColor`
+
+指定刷新指示器下显示的文字的颜色。
+
+| 类型 | 必需 | 平台 |
+| ------------------ | ---- | ---- |
+| [color](colors.md) | 否 | iOS |
diff --git a/cnwebsite/versioned_docs/version-0.85/releases/release-levels.md b/cnwebsite/versioned_docs/version-0.85/releases/release-levels.md
new file mode 100644
index 00000000000..e427ec9a0a4
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/releases/release-levels.md
@@ -0,0 +1,66 @@
+---
+id: release-levels
+title: 发布级别
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+React Native 为社区提供了在单个新功能的设计和实现几乎完成后就立即采用它们的能力,甚至在它们被包含在稳定版本之前。这种方法称为**发布级别**。
+
+您可以配置 React Native 的发布级别,使您的 React Native 实例在初始化时将功能标志设置为 `EXPERIMENTAL`、`CANARY` 或 `STABLE` 模式。
+
+:::note
+这种方法类似于 [React 中的 Canary 和 Experimental 版本](https://react.dev/blog/2023/05/03/react-canaries),但有一个关键区别:无论发布级别如何,都使用相同版本的 React JS 和 React Native 代码。
+React Native 也不使用 `@canary` 或 `@experimental` NPM 标签,因为发布级别可用于 React Native 的稳定版本和每夜构建版本。
+:::
+
+此外,将发布级别设置为 `EXPERIMENTAL` 或 `CANARY` **不会**导致使用 `react@nightly` 或 `react@canary`,这是由于 react-native 使用 React 版本的方式([您可以在这里阅读更多信息](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Renderer/README.md#react--react-native-versions))。
+
+## 何时使用每个发布级别
+
+- **`STABLE`**:
+ - 用于所有生产应用和不需要提前访问未发布功能的库。
+ - 这是稳定版本和每夜构建版本的默认级别。
+- **`CANARY`:**
+ - 如果您是框架作者、高级应用开发人员,或需要在功能在稳定版本中发布之前测试或采用新功能,请使用此级别。
+ - 不建议用于生产或面向用户的应用程序。
+- **`EXPERIMENTAL`:**
+ - 仅用于测试和为开发早期阶段的新功能提供反馈
+ - 不建议用于生产或面向用户的应用程序。
+
+## 如何使用 Canary 和 Experimental 初始化 React Native
+
+### Android
+
+`DefaultNewArchitectureEntryPoint` 类现在有一个 `releaseLevel` 属性(默认值:`STABLE`)。
+功能标志系统使用此属性为所选的发布级别选择适当的功能标志集。
+
+```kotlin title="示例用法"
+DefaultNewArchitectureEntryPoint.releaseLevel = ReleaseLevel.CANARY
+DefaultNewArchitectureEntryPoint.load()
+```
+
+构建系统为每个发布级别生成不同的功能标志覆盖类,确保为每个阶段启用正确的功能。
+
+### iOS
+
+`RCTReactNativeFactory` 类现在有一个接受 `releaseLevel` 参数的初始化器。功能标志设置使用此参数来选择正确的功能标志覆盖。
+
+
+
+
+```objc title="AppDelegate.mm"
+[[RCTReactNativeFactory alloc] initWithDelegate:delegate releaseLevel:Canary];
+```
+
+
+
+
+```swift title="AppDelegate.swift"
+let factory = RCTReactNativeFactory(delegate: delegate, releaseLevel: RCTReleaseLevel.Canary)
+```
+
+
+
+
+系统确保每个应用实例只有一个发布级别处于活动状态,如果创建具有不同发布级别的多个工厂,将会崩溃。
diff --git a/cnwebsite/versioned_docs/version-0.85/releases/releases.md b/cnwebsite/versioned_docs/version-0.85/releases/releases.md
new file mode 100644
index 00000000000..4926b29c9b2
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/releases/releases.md
@@ -0,0 +1,33 @@
+---
+id: releases
+title: 发布概览
+---
+
+import ReleasesTable from '@site/src/components/releases/ReleasesTable';
+
+React Native 的新版本**每两个月**发布一次,通常每年会有六(6)个新的次版本。
+
+以下是最近和即将发布的 React Native 版本的时间表和当前状态:
+
+
+
+表格中呈现的不同支持级别定义如下:
+
+- **Future(未来)**
+ - 在新版本分支被切出后,创建新的候选版本(Release Candidates)以允许社区测试即将到来的版本非常重要。新的 RC 版本会以很快的节奏发布,只要可行就会立即发布。
+- **Active(活跃)**
+ - 处于活跃支持中的稳定版本会频繁接收更新。最新稳定版具有最高优先级,在其稳定周期开始时(.0 版本发布后),会尽快进行多次补丁以稳定版本,并确保社区获得良好的升级体验。
+- **End of Cycle(周期结束)**
+ - 处于此支持级别的版本将接收较少的补丁,除非需要解决一些重要的回归问题。一旦下一个版本成为新的最新稳定版,在周期结束的版本移至不受支持之前,将产生最后一个补丁版本,其中包含最新收到的挑选请求。
+- **Unsupported(不受支持)**
+ - 当版本处于不受支持阶段时,不会有新的版本发布。只有非常重要的回归可能会创建此规则的例外;建议使用不受支持版本的代码库尽快升级。
+
+## 对稳定性的承诺
+
+为了支持用户升级 React Native 版本,我们承诺维护**最新的 3 个次版本系列**(例如,当 0.78 是最新版本时,维护 0.78.x、0.77.x 和 0.76.x)。
+
+对于这些版本,我们将定期发布更新和错误修复。
+
+您可以在 [react-native-releases 工作组](https://github.com/reactwg/react-native-releases/blob/main/docs/support.md)上阅读更多关于我们的支持政策。
+
+有关我们的版本控制以及我们认为什么是破坏性变更的更多信息,请访问我们的[版本策略](./releases/versioning-policy)页面。
diff --git a/cnwebsite/versioned_docs/version-0.85/releases/versioning-policy.md b/cnwebsite/versioned_docs/version-0.85/releases/versioning-policy.md
new file mode 100644
index 00000000000..62ed2c7ce22
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/releases/versioning-policy.md
@@ -0,0 +1,111 @@
+---
+title: 版本策略
+---
+
+本页面描述了我们对 `react-native` 包遵循的版本控制策略。
+
+我们通过手动和自动化测试彻底测试每个版本的 React Native,以确保质量不会下降。
+
+React Native 的 `stable` 频道遵循下面描述的 0.x.y 发布策略。
+
+React Native 还提供 `nightly` 发布频道,以鼓励对实验性功能的早期反馈。
+
+本页面描述了我们对 `react-native` 以及 `@react-native` 范围下的包的版本号的方法。
+
+## 稳定发布版本
+
+React Native 定期发布稳定版本。
+
+我们遵循 0.x.y 版本控制模式:
+
+- 破坏性变更将在新的次版本中发布,即我们增加 x 数字(例如:0.78.0 到 0.79.0)。
+- 新功能和 API 也将在新的次版本中发布,即我们增加 x 数字(例如:0.78.0 到 0.79.0)。
+- 关键错误修复将在新的补丁版本中发布,即我们增加 y 数字(例如:0.78.1 到 0.78.2)。
+
+稳定版本定期发布,最新版本在 NPM 上标记为 `latest`。
+
+具有相同次版本号的一系列发布称为**次版本系列**(例如,0.76.x 是 0.76.0、0.76.1、0.76.2 等的次版本系列)。
+
+您可以在[发布页面](./)上阅读更多关于我们**对稳定性的承诺**。
+
+### 破坏性变更
+
+破坏性变更对每个人来说都很不方便,我们正在努力将它们最小化到最低限度。我们在每个稳定版本中发布的所有破坏性变更将在以下位置突出显示:
+
+- [React Native Changelog](https://github.com/facebook/react-native/blob/main/CHANGELOG.md) 的 _Breaking_ 和 _Removed_ 部分
+- 每个版本博客文章的 _Breaking Changes_ 部分
+
+对于每个破坏性变更,我们承诺解释其背后的原因,如果可能的话提供替代 API,并最小化对最终用户的影响。
+
+### 什么是破坏性变更?
+
+我们认为 React Native 的破坏性变更包括:
+
+- 不兼容的 API 变更(即 API 被更改或删除,导致您的代码由于该变更而无法编译/运行)。示例:
+ - 任何 JS/Java/Kotlin/Obj-c/C++ API 的更改需要您更改代码才能编译。
+ - `@react-native/codegen` 内部不向后兼容的更改。
+- 重大的行为/运行时变更。示例:
+ - 属性的布局逻辑发生巨大变化。
+- 开发体验的重大变更。示例:
+ - 调试功能被完全移除。
+- 任何传递依赖项的主版本升级。示例:
+ - 将 React 从 18.x 升级到 19.x
+ - 在 Android 上将 Target SDK 从 34 升级到 35)。
+- 减少我们支持的平台版本。示例:
+ - 在 Android 上将最小 SDK 从 21 升级到 23
+ - 将最小 iOS 版本升级到 15.1。
+
+我们不认为这些变更是破坏性的:
+
+- 修改以 `unstable_` 前缀开头的 API:这些 API 暴露实验性功能,我们对它们的最终形态不够自信。通过使用 `unstable_` 前缀发布这些功能,我们可以更快地迭代并更快地获得稳定的 API。
+- 对私有或内部 API 的更改:这些 API 通常以 `internal_`、`private_` 为前缀,或存在于 `internal/` 或 `private/` 文件夹/包中。虽然由于工具限制,其中一些 API 可能具有公共可见性,但我们不认为它们是公共 API 的一部分,因此我们会在没有事先通知的情况下更改它们。
+ - 同样,如果您访问内部属性名称,如 `__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED` 或 `__reactInternalInstance$uk43rzhitjg`,则没有任何保证。您需要自负风险。
+ - 使用 `@FrameworkAPI` 注释的类也被视为内部的
+- 对工具/开发 API 的更改:React Native 的某些公共 API 保留用于与框架和其他工具的集成。例如,某些 Metro API 或 React Native DevTools API 应该仅由其他框架或工具使用。对这些 API 的更改直接与受影响的工具讨论,不被视为破坏性变更(我们不会在发布博客文章中广泛传达它们)。
+- 开发警告:由于警告不影响运行时行为,我们可能会在任何版本之间添加新警告或修改现有警告。
+
+如果我们预计某项变更会在社区中造成广泛问题,我们仍将尽最大努力为生态系统提供渐进的迁移路径。
+
+### 弃用周期
+
+随着我们不断开发和发展 React Native,我们编写新的 API,有时我们需要弃用现有的 API。这些 API 将经历弃用周期。
+
+一旦 API 被弃用,它将**也**在**后续**的稳定版本中保持可用。
+
+例如:如果一个 API 在 React Native 0.76.x 中被弃用,它仍将在 0.77.x 中可用,并且不会在 React Native 0.78.x 之前被移除。
+
+有时我们决定将弃用的 API 保留更长时间,如果我们觉得生态系统需要更多时间来迁移。对于这些 API,我们通常会提供警告以帮助用户迁移。
+
+## 发布频道
+
+React Native 依靠一个蓬勃发展的开源社区来提交错误报告、打开拉取请求和提交 RFC。为了鼓励反馈,我们确实支持多个发布频道。
+
+:::note
+本节与在框架、库或开发工具上工作的开发人员最相关。主要使用 React Native 构建面向用户的应用程序的开发人员不需要担心 latest 以外的发布频道。
+:::
+
+### latest
+
+`latest` 用于稳定的、符合 semver 的 React Native 版本。这是您从 npm 安装 React Native 时获得的版本。这是您今天已经在使用的频道。直接使用 React Native 的面向用户的应用程序使用此频道。
+
+我们定期发布更新的 React Native 次版本系列,并更新 `latest` 标签以反映最新的稳定版本。
+
+### next
+
+在我们宣布新的 React Native 版本稳定之前,我们会发布一系列**候选版本**,从 RC0 开始。这些版本是预发布版本(遵循版本控制模式 `0.79.0-rc.0`),在 NPM 上标记为 `next`。
+
+当新的分支切割发生并且 RC 开始在 NPM 和 GitHub 上发布时,最好针对 React Native 的 `next` 版本测试您的库/框架。
+
+这将确保您的项目将继续与即将发布的 React Native 版本良好配合。
+
+但是,不要直接在面向用户的应用程序中使用预发布版本/RC,因为它们不被视为生产就绪。
+
+### nightly
+
+我们还发布 `nightly` 发布频道。每夜构建版本每天从 [facebook/react-native](https://github.com/facebook/react-native) 的 `main` 分支发布。每夜构建版本被视为 React Native 的不稳定版本,不建议用于生产。
+
+每夜构建版本遵循版本控制模式 `0.80.0-nightly--`,其中 `` 是每夜构建的日期,`` 是用于发布此每夜构建的提交的 SHA。
+
+每夜构建版本仅供测试目的,我们不保证每夜构建之间的行为不会改变。它们不遵循我们用于 latest/next 版本的 semver 协议。
+
+最好设置一个 CI 工作流程,每天针对 react-native@nightly 版本测试您的库,以确保您的库将继续与未来的版本配合使用。
diff --git a/cnwebsite/versioned_docs/version-0.85/render-pipeline.md b/cnwebsite/versioned_docs/version-0.85/render-pipeline.md
new file mode 100644
index 00000000000..a4754b034a0
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/render-pipeline.md
@@ -0,0 +1,232 @@
+---
+id: render-pipeline
+title: 渲染,提交与挂载(渲染流水线)
+---
+
+> 文档介绍了即将发布的新渲染器 Fabric 的架构。
+
+React Native 渲染器通过一系列加工处理,将 React 代码渲染到宿主平台。这一系列加工处理就是渲染流水线(pipeline),它的作用是初始化渲染和 UI 状态更新。 接下来介绍的是渲染流水线,及其在各种场景中的不同之处。
+
+(译注:pipeline 的原义是将计算机指令处理过程拆分为多个步骤,并通过多个硬件处理单元并行执行来加快指令执行速度。其具体执行过程类似工厂中的流水线,并因此得名。)
+
+渲染流水线可大致分为三个阶段:
+
+- 渲染(Render):在 JavaScript 中,React 执行那些产品逻辑代码创建 React 元素树(React Element Trees)。然后在 C++ 中,用 React 元素树创建 React 影子树(React Shadow Tree)。
+- 提交(Commit):在 React 影子树完全创建后,渲染器会触发一次提交。这会将 React 元素树和新创建的 React 影子树的提升为“下一棵要挂载的树”。 这个过程中也包括了布局信息计算。
+- 挂载(Mount):React 影子树有了布局计算结果后,它会被转化为一个宿主视图树(Host View Tree)。
+
+> 名词解释
+>
+> React 元素树(React Element Trees):React 元素树是通过 JavaScript 中的 React 创建的,该树由一系类 React 元素组成。一个 React 元素就是一个普通的 JavaScript 对象,它描述了应该在屏幕中展示什么。一个元素包括属性 props、样式 styles、子元素 children。React 元素分为两类:React 复合组件实例(React Composite Components)和 React 宿主组件(React Host Components)实例,并且它只存在于 JavaScript 中。
+>
+> React 影子树(React Shadow Tree):React 影子树是通过 Fabric 渲染器创建的,树由一系列 React 影子节点组成。一个 React 影子节点是一个对象,代表一个已经挂载的 React 宿主组件,其包含的属性 props 来自 JavaScript。它也包括布局信息,比如坐标系 x、y,宽高 width、height。在新渲染器 Fabric 中,React 影子节点对象只存在于 C++ 中。而在老架构中,它存在于手机运行时的堆栈中,比如 Android 的 JVM。
+>
+> 宿主视图树(Host View Tree):宿主视图树就是一系列的宿主视图。宿主平台有 Android 平台、iOS 平台等等。在 Android 上,宿主视图就是 `android.view.ViewGroup`实例、 `android.widget.TextView`实例等等。宿主视图就像积木一样地构成了宿主视图树。每个宿主视图的大小和坐标位置基于的是 `LayoutMetrics`,而 `LayoutMetrics`是通过布局引擎 Yoga 计算出来的。宿主视图的样式和内容信息,是从 React 影子树中得到的。
+
+> 渲染流水线的各个阶段可能发生在不同的线程中,更详细的信息可以参考线程模型部分。
+
+
+
+渲染流水线存在三种不同场景:
+
+1. 初始化渲染
+2. React 状态更新
+3. React Native 渲染器的状态更新
+
+---
+
+### 初始化渲染
+
+#### 渲染阶段
+
+想象一下你准备渲染一个组件:
+
+```jsx
+function MyComponent() {
+ return (
+
+ Hello, World
+
+ );
+}
+
+//
+```
+
+在上面的例子中,` `是 React 元素。React 会将 React 元素简化为最终的 React 宿主组件。每一次都会递归地调用函数组件 MyComponet ,或类组件的 render 方法,直至所有的组件都被调用过。现在,你拥有一棵 React 宿主组件的 React 元素树。
+
+
+
+> 名词解释:
+>
+> React 组件(React Component):React 组件就是 JavaScript 函数或者类,描述如何创建 React 元素。
+>
+> React 复合组件(React Composite Components):React 组件的 render 方法中,包括其他 React 复合组件和 React 宿主组件。(译注:复合组件就是开发者声明的组件)
+>
+> React 宿主组件(React Host Components):React 组件的视图是通过宿主视图,比如 ``、``,实现的。在 Web 中,ReactDOM 的宿主组件就是 ``标签、`
`标签代表的组件。
+
+在元素简化的过程中,每调用一个 React 元素,渲染器同时会同步地创建 React 影子节点。这个过程只发生在 React 宿主组件上,不会发生在 React 复合组件上。比如,一个 `
`会创建一个 `ViewShadowNode` 对象,一个``会创建一个`TextShadowNode`对象。注意,``并没有直接对应的 React 影子节点。
+
+在 React 为两个 React 元素节点创建一对父子关系的同时,渲染器也会为对应的 React 影子节点创建一样的父子关系。这就是影子节点的组装方式。
+
+**其他细节**
+
+- 创建 React 影子节点、创建两个影子节点的父子关系的操作是同步的,也是线程安全的。该操作的执行是从 React(JavaScript)到渲染器(C++)的,大部分情况下是在 JavaScript 线程上执行的。(译注:后面线程模型有解释)
+- React 元素树和元素树中的元素并不是一直存在的,它只一个当前视图的描述,而最终是由 React “fiber” 来实现的。每一个 “fiber” 都代表一个宿主组件,存着一个 C++ 指针,指向 React 影子节点。这些都是因为有了 JSI 才有可能实现的。学习更多关于 “fibers” 的资料参考[这篇文档](https://github.com/acdlite/react-fiber-architecture#what-is-a-fiber)。
+- React 影子树是不可变的。为了更新任意的 React 影子节点,渲染器会创建了一棵新的 React 影子树。为了让状态更新更高效,渲染器提供了 clone 操作。更多细节可参考后面的 React 状态更新部分。
+
+在上面的示例中,各个渲染阶段的产物如图所示:
+
+
+
+#### 提交阶段
+
+在 React 影子树创建完成后,渲染器触发了一次 React 元素树的提交。
+
+提交阶段(Commit Phase)由两个操作组成:布局计算和树的提升。
+
+- **布局计算(Layout Calculation)**:这一步会计算每个 React 影子节点的位置和大小。在 React Native 中,每一个 React 影子节点的布局都是通过 Yoga 布局引擎来计算的。实际的计算需要考虑每一个 React 影子节点的样式,该样式来自于 JavaScript 中的 React 元素。计算还需要考虑 React 影子树的根节点的布局约束,这决定了最终节点能够拥有多少可用空间。
+
+
+
+- **树提升,从新树到下一棵树(Tree Promotion,New Tree → Next Tree)**:这一步会将新的 React 影子树提升为要挂载的下一棵树。这次提升代表着新树拥有了所有要挂载的信息,并且能够代表 React 元素树的最新状态。下一棵树会在 UI 线程下一个“tick”进行挂载。(译注:tick 是 CPU 的最小时间单元)
+
+**更多细节**
+
+- 这些操作都是在后台线程中异步执行的。
+- 绝大多数布局计算都是 C++ 中执行,只有某些组件,比如 Text、TextInput 组件等等,的布局计算是在宿主平台执行的。文字的大小和位置在每个宿主平台都是特别的,需要在宿主平台层进行计算。为此,Yoga 布局引擎调用了宿主平台的函数来计算这些组件的布局。
+
+#### 挂载阶段
+
+
+
+挂载阶段(Mount Phase)会将已经包含布局计算数据的 React 影子树,转换为以像素形式渲染在屏幕中的宿主视图树。请记住,这棵 React 元素树看起来是这样的:
+
+```jsx
+
+ Hello, World
+
+```
+
+站在更高的抽象层次上,React Native 渲染器为每个 React 影子节点创建了对应的宿主视图,并且将它们挂载在屏幕上。在上面的例子中,渲染器为`` 创建了`android.view.ViewGroup` 实例,为 `` 创建了文字内容为“Hello World”的 `android.widget.TextView`实例 。iOS 也是类似的,创建了一个 `UIView` 并调用 `NSLayoutManager` 创建文本。然后会为宿主视图配置来自 React 影子节点上的属性,这些宿主视图的大小位置都是通过计算好的布局信息配置的。
+
+
+
+更详细地说,挂载阶段由三个步骤组成:
+
+- **树对比(Tree Diffing):** 这个步骤完全用的是 C++ 计算的,会对比“已经渲染的树”(previously rendered tree)和”下一棵树”之间的差异。计算的结果是一系列宿主平台上的原子变更操作,比如 `createView`, `updateView`, `removeView`, `deleteView` 等等。在这个步骤中,还会将 React 影子树拍平,来避免不必要的宿主视图创建。关于视图拍平的算法细节可以在后文找到。
+- **树提升,从下一棵树到已渲染树(Tree Promotion,Next Tree → Rendered Tree):**在这个步骤中,会自动将“下一棵树”提升为“先前渲染的树”,因此在下一个挂载阶段,树的对比计算用的是正确的树。
+- **视图挂载(View Mounting):**这个步骤会在对应的原生视图上执行原子变更操作,该步骤是发生在原生平台的 UI 线程的。
+
+**更多细节**
+
+- 挂载阶段的所有操作都是在 UI 线程同步执行的。如果提交阶段是在后台线程执行,那么在挂载阶段会在 UI 线程的下一个“tick”执行。另外,如果提交阶段是在 UI 线程执行的,那么挂载阶段也是在 UI 线程执行。
+- 挂载阶段的调度和执行很大程度取决于宿主平台。例如,当前 Android 和 iOS 挂载层的渲染架构是不一样的。
+- 在初始化渲染时,“先前渲染的树”是空的。因此,树对比(tree diffing)步骤只会生成一系列仅包含创建视图、设置属性、添加视图的变更操作。而在接下来的 React 状态更新场景中,树对比的性能至关重要。
+- 在当前生产环境的测试中,在视图拍平之前,React 影子树通常由大约 600-1000 个 React 影子节点组成。在视图拍平之后,树的节点数量会减少到大约 200 个。在 iPad 或桌面应用程序上,这个节点数量可能要乘个 10。
+
+### React 状态更新
+
+接下来,我们继续看 React 状态更新时,渲染流水线(render pipeline)的各个阶段是什么样的。假设你在初始化渲染时,渲染的是如下组件:
+
+```jsx
+function MyComponent() {
+ return (
+
+
+
+
+ );
+}
+```
+
+应用我们在初始化渲染部分学的知识,你可以得到如下的三棵树:
+
+
+
+请注意,节点 3 对应的宿主视图背景是**红的**,而**节点 4 **对应的宿主视图背景是**蓝的**。假设 JavaScript 的产品逻辑是,将第一个内嵌的``的背景颜色由红色改为黄色。新的 React 元素树看起来大概是这样:
+
+```jsx
+
+
+
+
+```
+
+**React Native 是如何处理这个更新的?**
+
+从概念上讲,当发生状态更新时,为了更新已经挂载的宿主视图,渲染器需要直接更新 React 元素树。 但是为了线程的安全,React 元素树和 React 影子树都必须是不可变的(immutable)。这意味着 React 并不能直接改变当前的 React 元素树和 React 影子树,而是必须为每棵树创建一个包含新属性、新样式和新子节点的新副本。
+
+让我们继续探究状态更新时,渲染流水线的各个阶段发生了什么。
+
+#### 渲染阶段
+
+
+
+React 要创建了一个包含新状态的新的 React 元素树,它就要复制所有变更的 React 元素和 React 影子节点。 复制后,再提交新的 React 元素树。
+
+React Native 渲染器利用结构共享的方式,将不可变特性的开销变得最小。为了更新 React 元素的新状态,从该元素到根元素路径上的所有元素都需要复制。 **但 React 只会复制有新属性、新样式或新子元素的 React 元素**,任何没有因状态更新发生变动的 React 元素都不会复制,而是由新树和旧树共享。
+
+在上面的例子中,React 创建新树使用了这些操作:
+
+1. CloneNode(**Node 3**, `{backgroundColor: 'yellow'}`) → **Node 3'**
+2. CloneNode(**Node 2**) → **Node 2'**
+3. AppendChild(**Node 2'**, **Node 3'**)
+4. AppendChild(**Node 2'**, **Node 4**)
+5. CloneNode(**Node 1**) → **Node 1'**
+6. AppendChild(**Node 1'**, **Node 2'**)
+
+操作完成后,**节点 1'(Node 1')**就是新的 React 元素树的根节点。我们用 **T** 代表“先前渲染的树”,用 **T'** 代表“新树”。
+
+
+
+注意节点 4 在 **T** and **T'** 之间是共享的。结构共享提升了性能并减少了内存的使用。
+
+#### 提交阶段
+
+
+
+在 React 创建完新的 React 元素树和 React 影子树后,需要提交它们。
+
+- **布局计算(Layout Calculation):**状态更新时的布局计算,和初始化渲染的布局计算类似。一个重要的不同之处是布局计算可能会导致共享的 React 影子节点被复制。这是因为,如果共享的 React 影子节点的父节点引起了布局改变,共享的 React 影子节点的布局也可能发生改变。
+- **树提升(Tree Promotion ,New Tree → Next Tree):** 和初始化渲染的树提升类似。
+- **树对比(Tree Diffing):** 这个步骤会计算“先前渲染的树”(**T**)和“下一棵树”(**T'**)的区别。计算的结果是原生视图的变更操作。
+ - 在上面的例子中,这些操作包括:`UpdateView(**'Node 3'**, {backgroundColor: 'yellow'})`
+
+#### 挂载阶段
+
+
+
+- **树提升(Tree Promotion ,Next Tree → Rendered Tree):** 在这个步骤中,会自动将“下一棵树”提升为“先前渲染的树”,因此在下一个挂载阶段,树的对比计算用的是正确的树。
+- **视图挂载(View Mounting):**这个步骤会在对应的原生视图上执行原子变更操作。在上面的例子中,只有**视图 3(View 3)**的背景颜色会更新,变为黄色。
+
+
+
+### React Native 渲染器状态更新
+
+对于影子树中的大多数信息而言,React 是唯一所有方也是唯一事实源。并且所有来源于 React 的数据都是单向流动的。
+
+但有一个例外。这个例外是一种非常重要的机制:C++ 组件可以拥有状态,且该状态可以不直接暴露给 JavaScript,这时候 JavaScript (或 React)就不是唯一事实源了。通常,只有复杂的宿主组件才会用到 C++ 状态,绝大多数宿主组件都不需要此功能。
+
+例如,ScrollView 使用这种机制让渲染器知道当前的偏移量是多少。偏移量的更新是宿主平台的触发,具体地说是 ScrollView 组件。这些偏移量信息在 React Native 的 [measure](https://reactnative.dev/docs/direct-manipulation#measurecallback) 等 API 中有用到。 因为偏移量数据是由 C++ 状态持有的,所以源于宿主平台更新,不影响 React 元素树。
+
+从概念上讲,C++ 状态更新类似于我们前面提到的 React 状态更新,但有两点不同:
+
+- 因为不涉及 React,所以跳过了“渲染阶段”(Render phase)。
+- 更新可以源自和发生在任何线程,包括主线程。
+
+
+
+提交阶段(Commit Phase):在执行 C++ 状态更新时,会有一段代码把影子节点**(N)**的 C++ 状态设置为值 **S**。React Native 渲染器会反复尝试获取 **N** 的最新提交版本,并使用新状态 **S** 复制它 ,并将新的影子节点 **N'** 提交给影子树。如果 React 在此期间执行了另一次提交,或者其他 C++ 状态有了更新,本次 C++ 状态提交失败。这时渲染器将多次重试 C++ 状态更新,直到提交成功。这可以防止真实源的冲突和竞争。
+
+
+
+挂载阶段(Mount Phase)实际上与 React 状态更新的挂载阶段相同。渲染器仍然需要重新计算布局、执行树对比等操作。详细步骤在前面已经讲过了。
diff --git a/cnwebsite/versioned_docs/version-0.85/roottag.md b/cnwebsite/versioned_docs/version-0.85/roottag.md
new file mode 100644
index 00000000000..4cc50183f0b
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/roottag.md
@@ -0,0 +1,74 @@
+---
+id: roottag
+title: RootTag
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+`RootTag` 是用于标记 React Native 原生根视图层的不透明标识符(opaque identifier)。具体来说就是 `ReactRootView`(android) 或是 `RCTRootView`(iOS) 的实例 ID.
+
+## 什么时候使用 RootTag?
+
+对于绝大多数 React Native 开发者来说,一般你并不需要用到`RootTag`。
+
+`RootTag`在应用程序渲染**多个 React Native 根视图**且需要根据不同表面处理原生 API 调用时非常有用。一个例子是当应用程序使用原生导航,每个屏幕都是一个独立的 React Native 根视图。
+
+在原生导航中,每个 React Native 根视图都在平台的导航视图中渲染(例如,Android 的`Activity`,iOS 的`UINavigationViewController`)。通过这种方式,你可以利用平台的导航范式,如原生外观和导航转场。与原生导航 API 交互的功能可以通过[原生模块](https://reactnative.dev/docs/next/native-modules-intro)暴露给 React Native。
+
+例如,要更新屏幕的标题栏,你需要调用导航模块的 API `setTitle("更新的标题")`,但它需要知道要更新堆栈中的哪个屏幕。这里需要`RootTag`来识别根视图及其宿主容器。
+
+`RootTag`的另一个用例是当你的应用程序需要根据 JavaScript 调用的原始根视图来归属某个原生调用时。`RootTag`在这里是必要的,用于区分来自不同表面的调用源。
+
+## 如何使用 RootTag (如果你确实要用的话)
+
+在 0.65 及以下版本中,RootTag 通过[旧版上下文](https://github.com/facebook/react-native/blob/v0.64.1/Libraries/ReactNative/AppContainer.js#L56)访问。为了让 React Native 为 React 18 及以后版本中的并发特性做准备,我们正在迁移到最新的[Context API](https://react.dev/reference/react/createContext),通过 0.66 版本中的`RootTagContext`实现。0.65 版本同时支持旧版上下文和推荐的`RootTagContext`,以便开发者有时间迁移他们的调用点。请参阅重大变更摘要。
+
+如何通过`RootTagContext`访问`RootTag`。
+
+```js
+import {RootTagContext} from 'react-native';
+import NativeAnalytics from 'native-analytics';
+import NativeNavigation from 'native-navigation';
+
+function ScreenA() {
+ const rootTag = useContext(RootTagContext);
+
+ const updateTitle = title => {
+ NativeNavigation.setTitle(rootTag, title);
+ };
+
+ const handleOneEvent = () => {
+ NativeAnalytics.logEvent(rootTag, 'one_event');
+ };
+
+ // ...
+}
+
+class ScreenB extends React.Component {
+ static contextType: typeof RootTagContext = RootTagContext;
+
+ updateTitle(title) {
+ NativeNavigation.setTitle(this.context, title);
+ }
+
+ handleOneEvent() {
+ NativeAnalytics.logEvent(this.context, 'one_event');
+ }
+
+ // ...
+}
+```
+
+从 React 文档中了解更多关于[class](https://react.dev/reference/react/Component#static-contexttype)和[hooks](https://react.dev/reference/react/useContext)的 Context API。
+
+### 0.65 版本中的不兼容变更
+
+`RootTagContext` 之前被命名为 `unstable_RootTagContext`,并在 0.65 版本中更改为 `RootTagContext`。请更新您代码库中所有使用 `unstable_RootTagContext` 的地方。
+
+### 0.66 版本中的不兼容变更
+
+对`RootTag`的传统上下文访问将被移除,并由`RootTagContext`替代。从 0.65 版本开始,我们鼓励开发者主动将`RootTag`访问迁移到`RootTagContext`。
+
+## 未来的计划
+
+随着新的 React Native 架构的推进,`RootTag`将会有未来的迭代,目的是保持`RootTag`类型的不透明性,并防止 React Native 代码库中的频繁变动。请不要依赖于 RootTag 目前是数字类型的别名这一事实!如果您的应用依赖于 RootTags,请密切关注我们的版本变更日志,您可以在[这里](https://github.com/facebook/react-native/blob/main/CHANGELOG.md)找到。
diff --git a/cnwebsite/versioned_docs/version-0.85/running-on-device.md b/cnwebsite/versioned_docs/version-0.85/running-on-device.md
new file mode 100644
index 00000000000..b3075492351
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/running-on-device.md
@@ -0,0 +1,455 @@
+---
+id: running-on-device
+title: 在设备上运行
+hide_table_of_contents: true
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+在真机上仔细测试应用后再发布给用户总是不会错的。本文档将指导你通过必须的步骤在设备上运行 React Native 应用,为生产做准备。
+
+:::tip
+如果你使用 `create-expo-app` 来创建项目,可以通过 Expo Go 扫描运行 `npm start` 时显示的二维码来在设备上预览应用。更多信息请参阅 Expo 的[在设备上运行项目](https://docs.expo.dev/get-started/expo-go/)指南。
+:::
+
+
+
+
+## 在 Android 设备上运行应用
+
+#### 开发平台
+
+
+
+
+[//]: # 'macOS, Android'
+
+### 1. 开启 USB 调试
+
+在默认情况下 Android 设备只能从应用市场来安装应用。你需要开启 USB 调试才能自由安装开发版本的 APP。
+
+要开启 USB 调试,首先需要在 **设置** → **关于手机** → **软件信息** 中连续点击底部的`版本号`七次来启用"开发者选项"菜单。然后回到 **设置** → **开发者选项** 中开启"USB 调试"。
+
+### 2. 通过 USB 数据线连接设备
+
+现在我们设置一个 Android 设备来运行我们的 React Native 项目,通过 USB 将你的设备插入开发机器以继续。
+
+下面检查你的设备是否能正确连接到 ADB(Android Debug Bridge),使用`adb devices`命令:
+
+```shell
+$ adb devices
+List of devices attached
+emulator-5554 offline # Google emulator
+14ed2fcc device # Physical device
+```
+
+在右边那列看到 `device` 说明你的设备已经被正确连接了。注意,你每次只应当**连接一个设备**。
+
+:::note
+如果你在列表中看到 `unauthorized`,需要运行 `adb reverse tcp:8081 tcp:8081` 并在设备上允许 USB 调试。
+:::
+
+### 3. 运行应用
+
+在项目根目录下运行以下命令来在设备上安装并启动应用:
+
+
+
+
+```shell
+npm run android
+```
+
+
+
+
+```shell
+yarn android
+```
+
+
+
+
+:::note
+如果你收到"bridge configuration isn't available"错误,请参阅[使用 adb reverse](running-on-device.md#method-1-using-adb-reverse-recommended)。
+:::
+
+:::tip
+你还可以使用 `React Native CLI` 来生成和运行 `release` 版本(例如在项目根目录下:`yarn android --mode release`)。
+:::
+
+从设备上访问开发服务器
+
+在启用开发服务器的情况下,你可以快速的迭代修改应用,然后在设备上立即查看结果。有多种方式可以实现,取决于你是否有 USB 数据线或 Wi-Fi 网络。
+
+### Method 1: Using adb reverse (recommended)
+
+如果你的设备运行 Android 5.0(Lollipop)或更新版本,且已开启 USB 调试并通过 USB 连接到开发机器,你可以使用此方法。
+
+在命令行中运行:
+
+```shell
+$ adb -s reverse tcp:8081 tcp:8081
+```
+
+要查找设备名称,运行以下 adb 命令:
+
+```shell
+$ adb devices
+```
+
+现在你可以从[开发者菜单](debugging.md#opening-the-dev-menu)启用快速刷新(Fast Refresh)。每当你的 JavaScript 代码发生更改,应用就会重新加载。
+
+### Method 2: Connect via Wi-Fi
+
+你还可以通过 Wi-Fi 连接到开发服务器。你首先需要使用 USB 在设备上安装应用,完成之后便可以按照以下说明进行无线调试。在继续之前,你需要知道开发机器的当前 IP 地址。
+
+你可以在 **系统设置(或系统偏好设置)** → **网络** 中找到 IP 地址。
+
+1. 确保你的电脑和手机在**同一个** Wi-Fi 网络中。
+2. 在设备上打开 React Native 应用。
+3. 你会看到一个[红屏错误提示](debugging.md#logbox)。这是正常的,下面的步骤会解决。
+4. 打开应用内的[开发者菜单](debugging.md#opening-the-dev-menu)。
+5. 前往 **Dev Settings** → **Debug server host & port for device**。
+6. 输入你电脑的 IP 地址和端口号(例如 `10.0.1.1:8081`)。
+7. 回到**开发者菜单**然后选择 **Reload JS**。
+
+现在你可以从[开发者菜单](debugging.md#opening-the-dev-menu)启用快速刷新。每当你的 JavaScript 代码发生更改,应用就会重新加载。
+
+## 为生产编译应用
+
+你已经使用 React Native 构建了一个很棒的应用,现在你渴望在 Play Store 中发布它。该过程与任何其他原生 Android 应用相同,但需要考虑一些额外的注意事项。按照[生成签名 APK](signed-apk-android.md)的指南了解更多信息。
+
+
+
+
+[//]: # 'Windows, Android'
+
+### 1. 开启 USB 调试
+
+在默认情况下 Android 设备只能从应用市场来安装应用。你需要开启 USB 调试才能自由安装开发版本的 APP。
+
+要开启 USB 调试,首先需要在 **设置** → **关于手机** → **软件信息** 中连续点击底部的`版本号`七次来启用"开发者选项"菜单。然后回到 **设置** → **开发者选项** 中开启"USB 调试"。
+
+### 2. 通过 USB 数据线连接设备
+
+现在我们设置一个 Android 设备来运行我们的 React Native 项目,通过 USB 将你的设备插入开发机器以继续。
+
+下面检查你的设备是否能正确连接到 ADB(Android Debug Bridge),使用`adb devices`命令:
+
+```shell
+$ adb devices
+List of devices attached
+emulator-5554 offline # Google emulator
+14ed2fcc device # Physical device
+```
+
+在右边那列看到 `device` 说明你的设备已经被正确连接了。注意,你每次只应当**连接一个设备**。
+
+### 3. 运行应用
+
+在项目根目录下运行以下命令来在设备上安装并启动应用:
+
+
+
+
+```shell
+npm run android
+```
+
+
+
+
+```shell
+yarn android
+```
+
+
+
+
+:::tip
+你还可以使用 `React Native CLI` 来生成和运行 `release` 版本(例如在项目根目录下:`yarn android --mode release`)。
+:::
+
+从设备上访问开发服务器
+
+在启用开发服务器的情况下,你可以快速的迭代修改应用,然后在设备上立即查看结果。有多种方式可以实现,取决于你是否有 USB 数据线或 Wi-Fi 网络。
+
+### Method 1: Using adb reverse (recommended)
+
+如果你的设备运行 Android 5.0(Lollipop)或更新版本,且已开启 USB 调试并通过 USB 连接到开发机器,你可以使用此方法。
+
+在命令行中运行:
+
+```shell
+$ adb -s reverse tcp:8081 tcp:8081
+```
+
+要查找设备名称,运行以下 adb 命令:
+
+```shell
+$ adb devices
+```
+
+现在你可以从[开发者菜单](debugging.md#opening-the-dev-menu)启用快速刷新。每当你的 JavaScript 代码发生更改,应用就会重新加载。
+
+### Method 2: Connect via Wi-Fi
+
+你还可以通过 Wi-Fi 连接到开发服务器。你首先需要使用 USB 在设备上安装应用,完成之后便可以按照以下说明进行无线调试。在继续之前,你需要知道开发机器的当前 IP 地址。
+
+打开命令提示符并输入 `ipconfig` 来查找你电脑的 IP 地址([更多信息](https://windows.microsoft.com/en-us/windows/using-command-line-tools-networking-information))。
+
+1. 确保你的电脑和手机在**同一个** Wi-Fi 网络中。
+2. 在设备上打开 React Native 应用。
+3. 你会看到一个[红屏错误提示](debugging.md#logbox)。这是正常的,下面的步骤会解决。
+4. 打开应用内的[开发者菜单](debugging.md#opening-the-dev-menu)。
+5. 前往 **Dev Settings** → **Debug server host & port for device**。
+6. 输入你电脑的 IP 地址和端口号(例如 `10.0.1.1:8081`)。
+7. 回到**开发者菜单**然后选择 **Reload JS**。
+
+现在你可以从[开发者菜单](debugging.md#opening-the-dev-menu)启用快速刷新。每当你的 JavaScript 代码发生更改,应用就会重新加载。
+
+## 为生产编译应用
+
+你已经使用 React Native 构建了一个很棒的应用,现在你渴望在 Play Store 中发布它。该过程与任何其他原生 Android 应用相同,但需要考虑一些额外的注意事项。按照[生成签名 APK](signed-apk-android.md)的指南了解更多信息。
+
+
+
+
+[//]: # 'Linux, Android'
+
+### 1. 开启 USB 调试
+
+在默认情况下 Android 设备只能从应用市场来安装应用。你需要开启 USB 调试才能自由安装开发版本的 APP。
+
+要开启 USB 调试,首先需要在 **设置** → **关于手机** → **软件信息** 中连续点击底部的`版本号`七次来启用"开发者选项"菜单。然后回到 **设置** → **开发者选项** 中开启"USB 调试"。
+
+### 2. 通过 USB 数据线连接设备
+
+现在我们设置一个 Android 设备来运行我们的 React Native 项目,通过 USB 将你的设备插入开发机器以继续。
+
+接下来,使用 `lsusb` 检查制造商代码(在 Mac 上需要先[安装 lsusb](https://github.com/jlhonora/lsusb))。`lsusb` 的输出类似这样:
+
+```bash
+$ lsusb
+Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 001 Device 003: ID 22b8:2e76 Motorola PCS
+Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
+Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+```
+
+这些行代表了当前连接到你电脑的 USB 设备。
+
+你需要找到代表你手机的那一行。如果你不确定,可以先拔掉手机再运行一次命令:
+
+```bash
+$ lsusb
+Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub
+Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
+Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
+```
+
+你会看到拔掉手机后,包含手机型号的那一行(本例中的"Motorola PCS")从列表中消失了。
+
+`Bus 001 Device 003: ID 22b8:2e76 Motorola PCS`
+
+从上面这行中,你需要的是设备 ID 的前四位数字:
+
+`22b8:2e76`
+
+本例中是 `22b8`,这是 Motorola 的标识符。
+
+你需要将此标识符输入到 udev 规则中:
+
+```shell
+echo 'SUBSYSTEM=="usb", ATTR{idVendor}=="22b8", MODE="0666", GROUP="plugdev"' | sudo tee /etc/udev/rules.d/51-android-usb.rules
+```
+
+请将 `22b8` 替换为你上面获得的标识符。
+
+现在检查你的设备是否能正确连接到 ADB(Android Debug Bridge),使用`adb devices`命令:
+
+```shell
+$ adb devices
+List of devices attached
+emulator-5554 offline # Google emulator
+14ed2fcc device # Physical device
+```
+
+在右边那列看到 `device` 说明你的设备已经被正确连接了。注意,你每次只应当**连接一个设备**。
+
+### 3. 运行应用
+
+在项目根目录下运行以下命令来在设备上安装并启动应用:
+
+
+
+
+```shell
+npm run android
+```
+
+
+
+
+```shell
+yarn android
+```
+
+
+
+
+:::note
+如果你收到"bridge configuration isn't available"错误,请参阅[使用 adb reverse](running-on-device.md#method-1-using-adb-reverse-recommended).
+:::
+
+:::tip
+你还可以使用 `React Native CLI` 来生成和运行 `release` 版本(例如在项目根目录下:`yarn android --mode release`)。
+:::
+
+从设备上访问开发服务器
+
+在启用开发服务器的情况下,你可以快速的迭代修改应用,然后在设备上立即查看结果。有多种方式可以实现,取决于你是否有 USB 数据线或 Wi-Fi 网络。
+
+### Method 1: Using adb reverse (recommended)
+
+如果你的设备运行 Android 5.0(Lollipop)或更新版本,且已开启 USB 调试并通过 USB 连接到开发机器,你可以使用此方法。
+
+在命令行中运行:
+
+```shell
+$ adb -s reverse tcp:8081 tcp:8081
+```
+
+要查找设备名称,运行以下 adb 命令:
+
+```shell
+$ adb devices
+```
+
+现在你可以从[开发者菜单](debugging.md#opening-the-dev-menu)启用快速刷新。每当你的 JavaScript 代码发生更改,应用就会重新加载。
+
+### Method 2: Connect via Wi-Fi
+
+你还可以通过 Wi-Fi 连接到开发服务器。你首先需要使用 USB 在设备上安装应用,完成之后便可以按照以下说明进行无线调试。在继续之前,你需要知道开发机器的当前 IP 地址。
+
+打开终端并输入 `/sbin/ifconfig` 来查找你电脑的 IP 地址。
+
+1. 确保你的电脑和手机在**同一个** Wi-Fi 网络中。
+2. 在设备上打开 React Native 应用。
+3. 你会看到一个[红屏错误提示](debugging.md#logbox)。这是正常的,下面的步骤会解决。
+4. 打开应用内的[开发者菜单](debugging.md#opening-the-dev-menu)。
+5. 前往 **Dev Settings** → **Debug server host & port for device**。
+6. 输入你电脑的 IP 地址和端口号(例如 `10.0.1.1:8081`)。
+7. 回到**开发者菜单**然后选择 **Reload JS**。
+
+现在你可以从[开发者菜单](debugging.md#opening-the-dev-menu)启用快速刷新。每当你的 JavaScript 代码发生更改,应用就会重新加载。
+
+## 为生产编译应用
+
+你已经使用 React Native 构建了一个很棒的应用,现在你渴望在 Play Store 中发布它。该过程与任何其他原生 Android 应用相同,但需要考虑一些额外的注意事项。按照[生成签名 APK](signed-apk-android.md)的指南了解更多信息。
+
+
+
+
+
+
+
+## 在 iOS 设备上运行应用
+
+#### 开发平台
+
+
+
+
+[//]: # 'macOS, iOS'
+
+### 1. 通过 USB 数据线连接设备
+
+使用 USB 转 Lightning 或 USB-C 数据线将 iOS 设备连接到 Mac。导航到工程的`ios`文件夹,然后用 Xcode 打开`.xcodeproj`文件,如果使用了 CocoaPods 则打开`.xcworkspace`文件。
+
+如果这是第一次在 iOS 设备上运行应用,你可能需要注册设备用于开发。从 Xcode 菜单栏打开 **Product** 菜单,然后前往 **Destination**。从列表中查找并选择你的设备。Xcode 将注册你的设备用于开发。
+
+### 2. 配置代码签名
+
+如果还没有 [Apple 开发者账号](https://developer.apple.com/),先注册一个。
+
+在 Xcode Project 导航中选择你的 project,然后选择 main target(它应该和 project 同名)。查找"General"标签,前往"Signing"并确保在"Team"下拉菜单下选择了你的 Apple 开发者账号或团队。对 tests target(名称以 Tests 结尾,在 main target 下面)也**重复**同样的操作。
+
+
+
+### 3. 编译并运行应用
+
+如果一切设置正确,你的设备将出现在 Xcode 工具栏中作为构建目标,也会出现在设备面板(Shift ⇧ + Cmd ⌘ + 2 )中。现在可以按下 **Build and run** 按钮(Cmd ⌘ + R )或从 **Product** 菜单中选择 **Run**。应用将很快在你的设备上启动。
+
+
+
+:::note
+如果你遇到任何问题,请查看 Apple 的[在设备上启动应用](https://developer.apple.com/library/content/documentation/IDEs/Conceptual/AppDistributionGuide/LaunchingYourApponDevices/LaunchingYourApponDevices.html#//apple_ref/doc/uid/TP40012582-CH27-SW4)文档。
+:::
+
+从设备上访问开发服务器
+
+你还可以利用开发服务器在设备上快速迭代。只需要确保在和电脑同一个 Wi-Fi 网络中即可。摇晃设备打开[开发者菜单](debugging.md#opening-the-dev-menu),然后启用快速刷新。每当你的 JavaScript 代码发生更改,应用就会重新加载。
+
+
+
+### 常见问题
+
+:::tip
+如果你遇到任何问题,请确保你的 Mac 和设备在同一个网络中并且可以互相访问。许多使用强制门户的开放无线网络会阻止设备访问网络上的其他设备。此时你可以使用设备的个人热点功能。你也可以通过 USB 将 Mac 的互联网(Wi-Fi/以太网)连接共享给设备,然后通过此隧道连接到 bundler 以获得更高的传输速度。
+:::
+
+尝试连接到开发服务器时,你可能会看到一个[红屏错误](debugging.md#logbox):
+
+:::note
+Connection to `http://localhost:8081/debugger-proxy?role=client` timed out. Are you running node proxy? If you are running on the device, check if you have the right IP address in `RCTWebSocketExecutor.m`.
+:::
+
+要解决此问题,请检查以下几点。
+
+#### 1. Wi-Fi 网络
+
+确保你的电脑和手机在**同一个** Wi-Fi 网络中。
+
+#### 2. IP 地址
+
+确保构建脚本正确检测到了你电脑的 IP 地址(例如 `10.0.1.123`)。
+
+
+
+打开 **Report navigator** 标签,选择最近的 **Build** 然后搜索 `IP=` 后跟 IP 地址。嵌入到应用中的 IP 地址应该与你电脑的 IP 地址一致。
+
+## 为生产编译应用
+
+你已经使用 React Native 构建了一个很棒的应用,现在你渴望在 App Store 中发布它。该过程与任何其他原生 iOS 应用相同,但需要考虑一些额外的注意事项。按照[发布到 Apple App Store](publishing-to-app-store.md)的指南了解更多信息。
+
+
+
+
+[//]: # 'Windows, iOS'
+
+:::info
+构建 iOS 应用需要一台 Mac。或者你可以参考我们的[环境搭建指南](environment-setup),了解如何使用 Expo CLI 构建应用,这将允许你使用 Expo 客户端应用来运行你的应用。
+:::
+
+
+
+
+[//]: # 'Linux, iOS'
+
+:::info
+构建 iOS 应用需要一台 Mac。或者你可以参考我们的[环境搭建指南](environment-setup),了解如何使用 Expo CLI 构建应用,这将允许你使用 Expo 客户端应用来运行你的应用。
+:::
+
+
+
+
+
+
diff --git a/cnwebsite/versioned_docs/version-0.85/running-on-simulator-ios.md b/cnwebsite/versioned_docs/version-0.85/running-on-simulator-ios.md
new file mode 100644
index 00000000000..41fabb33b7a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/running-on-simulator-ios.md
@@ -0,0 +1,94 @@
+---
+id: running-on-simulator-ios
+title: 在 iOS 模拟器上运行
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+## 启动模拟器
+
+当你完成了 React Native 项目的初始化后,可以在新建的项目目录中运行以下命令:
+
+
+
+
+```shell
+npm run ios
+```
+
+
+
+
+```shell
+yarn ios
+```
+
+
+
+
+如果一切配置都正确,你应该很快就能看到你的应用在 iOS 模拟器中运行起来。
+
+## 指定模拟的设备类型
+
+你可以使用 `--simulator` 参数,在其后加上要使用的设备名称(字符串形式)来指定要模拟的设备。默认设备为 `"iPhone 14"`。如果你想在 iPhone SE(第三代)上运行应用,可以运行以下命令:
+
+
+
+
+```shell
+npm run ios -- --simulator="iPhone SE (3rd generation)"
+```
+
+
+
+
+```shell
+yarn ios --simulator "iPhone SE (3rd generation)"
+```
+
+
+
+
+设备名称对应于 Xcode 中可用的设备列表。你可以在终端中运行 `xcrun simctl list devices` 来查看可用的设备名称。
+
+### 指定设备版本
+
+如果你安装了多个 iOS 版本,还需要指定对应的版本。例如,要在 iPhone 14 Pro (16.0) 上运行应用,可以运行以下命令:
+
+
+
+
+```shell
+npm run ios -- --simulator="iPhone 14 Pro (16.0)"
+```
+
+
+
+
+```shell
+yarn ios --simulator "iPhone 14 Pro (16.0)"
+```
+
+
+
+
+## 指定 UDID
+
+你可以指定从 `xcrun simctl list devices` 命令返回的设备 UDID。例如,要使用 UDID 为 `AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA` 的设备运行应用,可以运行以下命令:
+
+
+
+
+```shell
+npm run ios -- --udid="AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
+```
+
+
+
+
+```shell
+yarn ios --udid "AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA"
+```
+
+
+
diff --git a/cnwebsite/versioned_docs/version-0.85/safeareaview.md b/cnwebsite/versioned_docs/version-0.85/safeareaview.md
new file mode 100644
index 00000000000..37a895886fa
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/safeareaview.md
@@ -0,0 +1,55 @@
+---
+id: safeareaview
+title: '🗑️ SafeAreaView'
+---
+
+:::warning 已弃用
+请改用 [react-native-safe-area-context](https://github.com/AppAndFlow/react-native-safe-area-context)。
+:::
+
+`SafeAreaView`会自动根据系统的各种导航栏、工具栏等预留出空间来渲染内部内容。更重要的是,它还会考虑到设备屏幕的局限,比如屏幕四周的圆角或是顶部中间不可显示的“刘海”区域。
+
+## 示例
+
+只需简单地把你原有的视图用`SafeAreaView`包起来,同时设置一个`flex: 1`的样式。当然可能还需要一些和你的设计相匹配的背景色。
+
+```SnackPlayer name=SafeAreaView
+import React from 'react';
+import { StyleSheet, Text, SafeAreaView } from 'react-native';
+
+const App = () => {
+ return (
+
+ Page content
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+});
+
+export default App;
+```
+
+---
+
+# 文档
+
+## Props
+
+### [View Props](view.md#props)
+
+继承了所有的[View Props](view.md#props).
+
+> As padding is used to implement the behavior of the component, padding rules in styles applied to a `SafeAreaView` will be ignored and can cause different results depending on the platform. See [#22211](https://github.com/facebook/react-native/issues/22211) for details.
+
+---
+
+### `emulateUnlessSupported`
+
+| 类型 | Required | Default |
+| ---- | -------- | ------- |
+| bool | No | true |
diff --git a/cnwebsite/versioned_docs/version-0.85/sample-application-movies.md b/cnwebsite/versioned_docs/version-0.85/sample-application-movies.md
new file mode 100644
index 00000000000..40a17b2d6ae
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/sample-application-movies.md
@@ -0,0 +1,503 @@
+---
+id: sample-application-movies
+title: 示例教程:电影列表
+---
+
+## 简介
+
+在本示例教程中,我们将编写一个简单的应用,可以从电影数据库中取得最近正在上映的 25 部电影,并在一个`FlatList`中展示出来。
+
+> 注意:此文档编写时间较早,组件采用class形式,可能与本网站其他函数式组件代码风格不一致,请留意写法上的区别。
+
+## 准备工作
+
+React Native 需要一些基础的配置工作,你可以参考[开始使用 React Native](getting-started.md)来进行。
+
+在所有依赖的软件都已经安装完毕后,请创建一个 React Native 工程和我们一起开始这次示例:
+
+```
+npx react-native init SampleAppMovies
+```
+
+这个命令会初始化一个工程、下载 React Native 的所有源代码和依赖包,最后在`SampleAppMovies/iOS/SampleAppMovies.xcodeproj`和`SampleAppMovies/android/app`下分别创建一个新的 XCode 工程(iOS)和一个 gradle 工程(Android)。
+
+## 开发
+
+想开发 iOS 版本,你现在可以在 XCode 中打开刚刚创建的工程(`SampleAppMovies/iOS/SampleAppMovies.xcodeproj`),然后只要按下`⌘+R`就可以构建并运行。这个操作会同时打开一个用于实现动态代码加载的 Node 服务(React Packager)。所以每当你修改代码,你只需要在模拟器中按下`⌘+R`,而无需重新在 XCode 中编译。
+
+想开发 Android 版本,先连接你的设备或启动模拟器,然后在`SampleAppMovies`目录下运行`react-native run-android`,就会构建工程(注意在第一次构建中会联网下载很多依赖,耗时较长。在国内的话务必使用稳定的 XX 工具,否则会一直失败)并自动安装到你的模拟器或者设备,同时启动用于实现动态代码加载的 Node 服务。当你修改代码之后,你需要打开摇一摇菜单(摇一下设备,或者按下设备的 Menu 键,或者在模拟器上按下 F2 或 Page Up,Genymotion 按下 ⌘+M),然后在菜单中点击“Reload JS”。
+
+### Hello World
+
+`npx react-native init`命令会创建一个指定名字的应用,我们刚才输入的命令就创建了一个名为 SampleAppMovies 的应用。这是一个简单的 Hello World 应用。你可以编辑`App.js`来做一些改动,然后在模拟器中按 ⌘+R 来看到修改的结果。
+
+### 模拟数据
+
+在我们真正从 Rotten Tomatoes(_译注:一个国外的电影社区_)抓取数据之前,我们先制造一些模拟数据来练一练手。在 Facebook 我们通常在 JS 文件的开头,紧跟着 import 语句之后声明一个常量,不过这不重要,你可以把它放在`App.js`的任意位置:
+
+```jsx
+const MOCKED_MOVIES_DATA = [
+ {
+ title: '标题',
+ year: '2015',
+ posters: {thumbnail: 'http://i.imgur.com/UePbdph.jpg'},
+ },
+];
+```
+
+> 译注:在 iOS 上使用 http 链接的图片地址可能不会显示,参见[这篇说明修改](https://segmentfault.com/a/1190000002933776)。
+> 从 Android9 开始,也会默认阻止 http 请求,请参考[相关配置](https://blog.csdn.net/qq_40347548/article/details/86766932)
+
+### 展现一个电影
+
+我们接下来要展现一个电影,绘制它的标题、年份、以及缩略图(_译注:这个过程我们通常会叫做“渲染/render”,后面我们都会用“渲染”这个词_)。渲染缩略图需要用到 Image 组件,所以把 Image 添加到对 React 的 import 列表中。
+
+```jsx
+import React, {Component} from 'react';
+import {Image, StyleSheet, Text, View} from 'react-native';
+```
+
+然后修改一下 render 函数,这样我们可以把上面创建的模拟数据渲染出来。
+
+```jsx
+ render() {
+ const movie = MOCKED_MOVIES_DATA[0];
+ return (
+
+ {movie.title}
+ {movie.year}
+
+
+ );
+ }
+```
+
+按下`⌘+R`或者`Reload JS`,现在你应该能看到文字"Title"和"2015",但现在 Image 组件没渲染任何东西,这是因为我们还没有为图片指定我们想要渲染的宽和高。这通过样式来实现。当我们修改样式的时候,我们也应该清理掉我们不再使用的样式。
+
+```jsx
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#F5FCFF',
+ },
+ thumbnail: {
+ width: 53,
+ height: 81,
+ },
+});
+```
+
+然后把它应用到 Image 组件上:
+
+```jsx
+
+```
+
+按下`⌘+R`或者`Reload JS`,现在图片应该可以被渲染出来了。
+
+| | |
+| -------------------------- | --------------------------- |
+|  |  |
+
+### 添加样式
+
+现在我们已经成功的把我们的数据渲染出来了,下面让我们把它弄的更好看一些。我想把文字放在图片的右边,然后把标题弄的大一些,并且水平居中:
+
+```
++---------------------------------+
+|+-------++----------------------+|
+|| || 标题 ||
+|| 图片 || ||
+|| || 年份 ||
+|+-------++----------------------+|
++---------------------------------+
+```
+
+所以我们需要增加一个 container 来实现一个水平布局内嵌套一个垂直布局。
+
+```jsx
+return (
+
+
+
+ {movie.title}
+ {movie.year}
+
+
+);
+```
+
+和之前相比并没有太多变化,我们增加了一个 container 来包装文字,然后把它移到了 Image 的后面(因为他们最终在图片的右边)。然后我们来看看样式要怎么改:
+
+```jsx
+ container: {
+ flex: 1,
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#F5FCFF',
+ },
+```
+
+我们用 Flexbox 来布局。如果你想了解更多,可以读读[这篇文章](https://css-tricks.com/snippets/css/a-guide-to-flexbox/)。
+
+在上面的代码片段中,我们用了一句`flexDirection: 'row'`来让我们的主容器的成员从左到右横向布局,而非默认的从上到下纵向布局。
+
+现在我们往`style`对象里增加另一个样式:
+
+```jsx
+ rightContainer: {
+ flex: 1,
+ },
+```
+
+这句话的作用是让`rightContainer`在父容器中占据 Image 之外剩下的全部空间。如果你还不是很理解的话,你可以往`rightContainer`里增加一个`backgroundColor`看一看,然后再去掉`flex:1`对比一下。你会发现去掉这一句后,容器会变成能容纳它孩子的最小大小。
+
+给文字添加样式就简单的多了:
+
+```jsx
+ title: {
+ fontSize: 20,
+ marginBottom: 8,
+ textAlign: 'center',
+ },
+ year: {
+ textAlign: 'center',
+ },
+```
+
+再按一次`⌘+R`或者`Reload JS`来看看最新的结果。
+
+| | |
+| -------------------------------- | --------------------------------- |
+|  |  |
+
+### 拉取真正的数据
+
+从 Rotten Tomatoes 的 API 拉取数据和学习 React Native 并没有什么直接关系,所以你也可以直接跳过本节。
+
+把下面的常量放到文件的最开头(通常在 import 下面)来创建我们请求数据所需的地址常量 REQUEST_URL
+
+```jsx
+/**
+ * 为了避免骚扰,我们用了一个样例数据来替代Rotten Tomatoes的API
+ * 请求,这个样例数据放在React Native的Github库中。
+ * 当然,由于众所周知的原因,这个地址可能国内访问也比较困难。
+ */
+const REQUEST_URL =
+ 'https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json';
+```
+
+首先在应用中创建一个初始的 null 状态,这样可以通过`this.state.movies == null`来判断我们的数据是不是已经被抓取到了。我们在服务器响应返回的时候执行`this.setState({movies: moviesData})`来改变这个状态。把下面这段代码放到我们的 React 类的 render 函数之前(下面注释中的“绑定操作”你可以看看这个[短视频教程](http://v.youku.com/v_show/id_XMTgyNzM0NjQzMg==.html)):
+
+```jsx
+ constructor(props) {
+ super(props); //这一句不能省略,照抄即可
+ this.state = {
+ movies: null, //这里放你自己定义的state变量及初始值
+ };
+ // 在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向不对
+ // 像下面这行代码一样,在constructor中使用bind是其中一种做法(还有一些其他做法,如使用箭头函数等)
+ this.fetchData = this.fetchData.bind(this);
+ }
+```
+
+组件加载完毕之后,就可以向服务器请求数据。`componentDidMount`是 React 组件的一个生命周期方法,它会在组件刚加载完成的时候调用一次,以后不会再被调用。React 中的各种生命周期方法请[参阅此文档](http://facebook.github.io/react/docs/component-specs.html)。
+
+```jsx
+ componentDidMount() {
+ this.fetchData();
+ }
+```
+
+现在我们来为组件添加`fetchData`函数。你所需要做的就是在 Promise 调用链结束后执行`this.setState({movies:data})`。在 React 的工作机制下,`setState`实际上会触发一次`重新渲染`的流程,此时 render 函数被触发,发现 this.state.movies 不再是`null`。
+
+```jsx
+ fetchData() {
+ fetch(REQUEST_URL)
+ .then((response) => response.json())
+ .then((responseData) => {
+ // 注意,这里使用了this关键字,为了保证this在调用时仍然指向当前组件,我们需要对其进行“绑定”操作
+ this.setState({
+ movies: responseData.movies,
+ });
+ });
+ }
+```
+
+现在我们来修改 render 函数。在电影数据加载完毕之前,先渲染一个“加载中”的视图;而如果电影数据已经加载完毕了,则渲染第一个电影数据。
+
+```jsx
+ render() {
+ if (!this.state.movies) {
+ return this.renderLoadingView();
+ }
+
+ const movie = this.state.movies[0];
+ return this.renderMovie(movie);
+ }
+
+ renderLoadingView() {
+ return (
+
+
+ 正在加载电影数据……
+
+
+ );
+ }
+
+ renderMovie(movie) {
+ return (
+
+
+
+ {movie.title}
+ {movie.year}
+
+
+ );
+ }
+```
+
+现在再按一次`⌘+R`或者`Reload JS`,你会首先看到“正在加载电影数据……”,然后在响应数据到达之后,看到第一个电影的信息。
+
+| | |
+| ----------------------------------- | ------------------------------------ |
+|  |  |
+
+## FlatList
+
+现在我们来让我们的应用能够渲染所有的数据而不是仅仅第一部电影。我们要用到的就是 FlatList 组件。
+
+为什么建议把内容放到 FlatList 里?比起直接渲染出所有的元素,或是放到一个 ScrollView 里有什么优势?这是因为尽管 React 很高效,渲染一个可能很大的元素列表还是会很慢。`FlatList`会安排视图的渲染,只显示当前在屏幕上的那些元素。而那些已经渲染好了但移动到了屏幕之外的元素,则会从原生视图结构中移除(以提高性能)。
+
+首先要做的事情:在文件最开头引入`FlatList`。
+
+```jsx
+import React, {Component} from 'react';
+import {
+ Image,
+ FlatList,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+```
+
+现在来修改 render 函数。当我们已经有了数据之后,渲染一个包含多个电影信息的 FlatList,而不仅仅是单个的电影。
+
+```jsx
+ render() {
+ if (!this.state.loaded) {
+ return this.renderLoadingView();
+ }
+
+ return (
+ item.id}
+ />
+ );
+ }
+```
+
+> keyExtractor
+> 此函数用于为给定的item生成一个不重复的key。Key的作用是使React能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。若不指定此函数,则默认抽取item.key作为key值。若item.key也不存在,则使用数组下标。
+
+你会注意到我们现在用到了`this.state`中的`data`。下一步就是在`constructor`生成的初始状态中添加一个空白的`data`。另外,我们现在要把数据存储在`data`中了,所以不再另外用`this.state.movies`来保存数据。我们可以在 state 里用一个布尔型的属性(`this.state.loaded`)来判断数据加载是否已经完成了。
+
+```jsx
+ constructor(props) {
+ super(props);
+ this.state = {
+ data: [],
+ loaded: false,
+ };
+ // 在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向不对
+ // 像下面这行代码一样,在constructor中使用bind是其中一种做法(还有一些其他做法,如使用箭头函数等)
+ this.fetchData = this.fetchData.bind(this);
+ }
+```
+
+同时我们也要修改`fetchData`方法来把数据添加到 data 里(注意这里使用了数组的 concat 方法生成新数组,不能直接在原数组上 push!):
+
+```jsx
+ fetchData() {
+ fetch(REQUEST_URL)
+ .then((response) => response.json())
+ .then((responseData) => {
+ // 注意,这里使用了this关键字,为了保证this在调用时仍然指向当前组件,我们需要对其进行“绑定”操作
+ this.setState({
+ data: this.state.data.concat(responseData.movies),
+ loaded: true,
+ });
+ });
+ }
+```
+
+`renderMovie`方法的构型也有变化(注意如果你要在这个方法中使用 this 关键字的话,需要怎么改?)。
+
+```jsx
+ renderMovie({ item }) {
+ // { item }是一种“解构”写法,请阅读ES2015语法的相关文档
+ // item也是FlatList中固定的参数名,请阅读FlatList的相关文档
+ return (
+
+
+
+ {item.title}
+ {item.year}
+
+
+ );
+ }
+```
+
+最后,我们再在`styles`对象里给`FlatList`添加一些样式。
+
+```jsx
+ list: {
+ paddingTop: 20,
+ backgroundColor: '#F5FCFF',
+ },
+```
+
+现在可以体现最终的结果了:
+
+| | |
+| --------------------------- | ---------------------------- |
+|  |  |
+
+为了实现一个完整功能的应用,接下来其实还有一些工作要做,譬如:添加导航器,搜索,加载更多,等等等等。
+
+### 最终的代码(App.js)
+
+```jsx
+import React, {Component} from 'react';
+
+import {
+ Image,
+ FlatList,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+
+const REQUEST_URL =
+ 'https://raw.githubusercontent.com/facebook/react-native/0.51-stable/docs/MoviesExample.json';
+
+export default class SampleAppMovies extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ data: [],
+ loaded: false,
+ };
+ // 在ES6中,如果在自定义的函数里使用了this关键字,则需要对其进行“绑定”操作,否则this的指向会变为空
+ // 像下面这行代码一样,在constructor中使用bind是其中一种做法(还有一些其他做法,如使用箭头函数等)
+ this.fetchData = this.fetchData.bind(this);
+ }
+
+ componentDidMount() {
+ this.fetchData();
+ }
+
+ fetchData() {
+ fetch(REQUEST_URL)
+ .then(response => response.json())
+ .then(responseData => {
+ // 注意,这里使用了this关键字,为了保证this在调用时仍然指向当前组件,我们需要对其进行“绑定”操作
+ this.setState({
+ data: this.state.data.concat(responseData.movies),
+ loaded: true,
+ });
+ });
+ }
+
+ render() {
+ if (!this.state.loaded) {
+ return this.renderLoadingView();
+ }
+
+ return (
+ item.id}
+ />
+ );
+ }
+
+ renderLoadingView() {
+ return (
+
+ Loading movies...
+
+ );
+ }
+
+ renderMovie({item}) {
+ // { item }是一种“解构”写法,请阅读ES2015语法的相关文档
+ // item也是FlatList中固定的参数名,请阅读FlatList的相关文档
+ return (
+
+
+
+ {item.title}
+ {item.year}
+
+
+ );
+ }
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ flexDirection: 'row',
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: '#F5FCFF',
+ },
+ rightContainer: {
+ flex: 1,
+ },
+ title: {
+ fontSize: 20,
+ marginBottom: 8,
+ textAlign: 'center',
+ },
+ year: {
+ textAlign: 'center',
+ },
+ thumbnail: {
+ width: 53,
+ height: 81,
+ },
+ list: {
+ paddingTop: 20,
+ backgroundColor: '#F5FCFF',
+ },
+});
+```
diff --git a/cnwebsite/versioned_docs/version-0.85/scrollview.md b/cnwebsite/versioned_docs/version-0.85/scrollview.md
new file mode 100644
index 00000000000..86062ce849c
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/scrollview.md
@@ -0,0 +1,775 @@
+---
+id: scrollview
+title: ScrollView
+---
+
+一个封装了平台的 ScrollView(滚动视图)的组件,同时还集成了触摸锁定的“响应者”系统。
+
+记住 ScrollView 必须有一个确定的高度才能正常工作,因为它实际上所做的就是将一系列不确定高度的子组件装进一个确定高度的容器(通过滚动操作)。要给 ScrollView 一个确定的高度的话,要么直接给它设置高度(不建议),要么确定所有的父容器都有确定的高度。一般来说我们会给 ScrollView 设置`flex: 1`以使其自动填充父容器的空余空间,但前提条件是所有的父容器本身也设置了 flex 或者指定了高度,否则就会导致无法正常滚动,你可以使用元素查看器来查找具体哪一层高度不正确。
+
+ScrollView 内部的其他响应者尚无法阻止 ScrollView 本身成为响应者。
+
+`ScrollView`和`FlatList`应该如何选择?ScrollView 会简单粗暴地把所有子元素一次性全部渲染出来。其原理浅显易懂,使用上自然也最简单。然而这样简单的渲染逻辑自然带来了性能上的不足。想象一下你有一个特别长的列表需要显示,可能有好几屏的高度。创建和渲染那些屏幕以外的 JS 组件和原生视图,显然对于渲染性能和内存占用都是一种极大的拖累和浪费。
+
+这就是为什么我们还有专门的`FlatList`组件。`FlatList`会惰性渲染子元素,只在它们将要出现在屏幕中时开始渲染。这种惰性渲染逻辑要复杂很多,因而 API 在使用上也更为繁琐。除非你要渲染的数据特别少,否则你都应该尽量使用`FlatList`,哪怕它们用起来更麻烦。
+
+此外`FlatList`还可以方便地渲染行间分隔线,支持多列布局,无限滚动加载等等。
+
+## 示例
+
+```SnackPlayer name=ScrollView%20Example
+import React from 'react';
+import {StyleSheet, Text, ScrollView, StatusBar} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => (
+
+
+
+
+ Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
+ eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
+ minim veniam, quis nostrud exercitation ullamco laboris nisi ut
+ aliquip ex ea commodo consequat. Duis aute irure dolor in
+ reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla
+ pariatur. Excepteur sint occaecat cupidatat non proident, sunt in
+ culpa qui officia deserunt mollit anim id est laborum.
+
+
+
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ paddingTop: StatusBar.currentHeight,
+ },
+ scrollView: {
+ backgroundColor: 'pink',
+ },
+ text: {
+ fontSize: 42,
+ padding: 12,
+ },
+});
+
+export default App;
+```
+
+---
+
+# 文档
+
+## Props
+
+### [View Props](view.md#props)
+
+继承了所有的[View Props](view#props).
+
+---
+
+### `StickyHeaderComponent`
+
+一个 React 组件,用于渲染粘性头部,应与`stickyHeaderIndices`一起使用。如果你的粘性头部使用了自定义变换(例如,当你希望列表具有可动画隐藏的头部时),你可能需要设置此组件。如果未提供组件,则将使用默认的 [`ScrollViewStickyHeader`](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js) 组件。
+
+| 类型 |
+| ------------------ |
+| component, element |
+
+---
+
+### `alwaysBounceHorizontal` iOS
+
+当此属性为 true 时,水平方向即使内容比滚动视图本身还要小,也可以弹性地拉动一截。当`horizontal={true}`时默认值为 true,否则为 false。
+
+| 类型 | 默认值 |
+| ---- | ----------------------------------------------------- |
+| bool | `true` when `horizontal={true}` `false` otherwise |
+
+---
+
+### `alwaysBounceVertical` iOS
+
+当此属性为 true 时,垂直方向即使内容比滚动视图本身还要小,也可以弹性地拉动一截。当`horizontal={true}`时默认值为 false,否则为 true。
+
+| 类型 | 默认值 |
+| ---- | --------------------------------------------------- |
+| bool | `false` when `vertical={true}` `true` otherwise |
+
+---
+
+### `automaticallyAdjustContentInsets` iOS
+
+当滚动视图放在一个导航条或者工具条后面的时候,iOS 系统是否要自动调整内容的范围。默认值为 true。(译注:如果你的 ScrollView 或 FlatList 的头部出现莫名其妙的空白,尝试将此属性置为 false)
+
+| 类型 | 必需 |
+| ---- | ---- |
+| bool | 否 |
+
+---
+
+### `automaticallyAdjustKeyboardInsets` iOS
+
+当键盘尺寸变化时,ScrollView 是否自动调整其 `contentInset` 和 `scrollViewInsets`。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `automaticallyAdjustsScrollIndicatorInsets` iOS
+
+控制 iOS 是否自动调整滚动指示器内边距。请参阅 Apple 的[文档](https://developer.apple.com/documentation/uikit/uiscrollview/3198043-automaticallyadjustsscrollindica)。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `bounces` iOS
+
+当值为 true 时,如果内容范围比滚动视图本身大,在到达内容末尾的时候,可以弹性地拉动一截。如果为 false,尾部的所有弹性都会被禁用,即使`alwaysBounce`属性为 true。默认值为 true。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `bouncesZoom` iOS
+
+当值为 true 时,使用手势缩放内容可以超过 min/max 的限制,然后在手指抬起之后弹回 min/max 的缩放比例。否则的话,缩放不能超过限制。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `canCancelContentTouches` iOS
+
+当值为 false 时,一旦有子节点响应触摸操作,即使手指开始移动也不会拖动滚动视图。默认值为 true(在以上情况下可以拖动滚动视图)。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `centerContent` iOS
+
+当值为 true 时,如果滚动视图的内容比视图本身小,则会自动把内容居中放置。当内容比滚动视图大的时候,此属性没有作用。默认值为 false。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `contentContainerStyle`
+
+这些样式会应用到一个内层的内容容器上,所有的子视图都会包裹在内容容器内。示例:
+
+```
+return (
+
+
+);
+...
+const styles = StyleSheet.create({
+ contentContainer: {
+ paddingVertical: 20
+ }
+});
+```
+
+| 类型 |
+| ------------------------------ |
+| [View Style](view-style-props) |
+
+---
+
+### `contentInset` iOS
+
+内容范围相对滚动视图边缘的坐标。默认为`{top: 0, left: 0, bottom: 0, right: 0}`。
+
+| 类型 | 默认值 |
+| -------------------------------------------------------------------- | ---------------------------------------- |
+| object: `{top: number, left: number, bottom: number, right: number}` | `{top: 0, left: 0, bottom: 0, right: 0}` |
+
+---
+
+### `contentInsetAdjustmentBehavior` iOS
+
+本属性用于指定安全区域内边距如何修改滚动视图的内容区域。
+
+| 类型 | 默认值 |
+| -------------------------------------------------------------- | --------- |
+| enum(`'automatic'`, `'scrollableAxes'`, `'never'`, `'always'`) | `'never'` |
+
+---
+
+### `contentOffset`
+
+用来手动设置初始的滚动坐标。
+
+| 类型 | 默认值 |
+| ----- | -------------- |
+| Point | `{x: 0, y: 0}` |
+
+---
+
+### `decelerationRate`
+
+一个浮点数,用于决定当用户抬起手指之后,滚动视图减速停下的速度。你也可以设置为`"normal"`或者`"fast"`,分别对应的是 iOS 上的`UIScrollViewDecelerationRateNormal`和 `UIScrollViewDecelerationRateFast`。
+
+- `'normal'`: iOS 上是 0.998,Android 上是 0.985(默认值)
+- `'fast'`: iOS 上是 0.99,Android 上是 0.9
+
+| 类型 | 默认值 |
+| ---------------------------------- | ---------- |
+| enum(`'fast'`, `'normal'`), number | `'normal'` |
+
+---
+
+### `directionalLockEnabled` iOS
+
+当值为真时,滚动视图在拖拽的时候会锁定只有垂直或水平方向可以滚动。默认值为 false
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `disableIntervalMomentum`
+
+当值为 true 时,滚动视图在拖拽的时候会停止在下一个索引(相对于释放时的滚动位置),无论手势有多快。这可以用于分页,当页面小于水平滚动视图的宽度或垂直滚动视图的高度时。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `disableScrollViewPanResponder`
+
+当值为 true 时,滚动视图的默认 JS 手势响应器会被禁用,并且滚动视图内部的触摸操作完全由其子组件控制。这在启用 `snapToInterval` 时特别有用,因为它不遵循典型的触摸模式。不要在常规的滚动视图使用场景中使用此属性,除非你启用了 `snapToInterval`,否则可能会导致意外的触摸操作。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `endFillColor` Android
+
+有时候滚动视图会占据比实际内容更多的空间。这种情况下可以使用此属性,指定以某种颜色来填充多余的空间,以避免设置背景和创建不必要的绘制开销。一般情况下并不需要这种高级优化技巧。
+
+| 类型 |
+| --------------- |
+| [color](colors) |
+
+---
+
+### `fadingEdgeLength` Android
+
+滚动内容的边缘会逐渐淡出。
+
+如果值大于 `0`,则会根据当前的滚动方向和位置设置淡出边缘,指示是否有更多内容可显示。
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| number | `0` |
+
+---
+
+### `horizontal`
+
+当此属性为 true 的时候,滚动视图的子视图会在水平方向上排成一行,而不是默认的在垂直方向上排成一列。默认值为 false。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `indicatorStyle` iOS
+
+设置滚动条的样式。
+
+- `'default'` 默认值,等同`black`。
+- `'black'`,黑色滚动条。
+- `'white'`,白色滚动条。
+
+| 类型 | 默认值 |
+| --------------------------------------- | ----------- |
+| enum(`'default'`, `'black'`, `'white'`) | `'default'` |
+
+---
+
+### `invertStickyHeaders`
+
+如果粘性头部应该固定在滚动视图的底部而不是顶部。通常用于反转的滚动视图中。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `keyboardDismissMode`
+
+用户拖拽滚动视图的时候,是否要隐藏软键盘。
+
+_跨平台可用的值_
+
+- `'none'` (默认值),拖拽时不隐藏软键盘。
+- `'on-drag'`,当拖拽开始的时候隐藏软键盘。
+
+_仅 iOS 可用的值_
+
+- `'interactive'`,软键盘伴随拖拽操作同步地消失,并且如果往上滑动会恢复键盘。安卓设备上不支持这个选项,会表现的和`none`一样。
+
+| 类型 | 默认值 |
+| --------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
+| enum(`'none'`, `'on-drag'`) Android
enum(`'none'`, `'on-drag'`, `'interactive'`) iOS
| `'none'` |
+
+---
+
+### `keyboardShouldPersistTaps`
+
+如果当前界面有软键盘,那么点击 scrollview 后是否收起键盘,取决于本属性的设置。(译注:很多人反应 TextInput 无法自动失去焦点/需要点击多次切换到其他组件等等问题,其关键都是需要将 TextInput 放到 ScrollView 中再设置本属性)
+
+- `'never'` (默认值),点击 TextInput 以外的子组件会使当前的软键盘收起。此时子元素不会收到点击事件。
+- `'always'`,键盘不会自动收起,ScrollView 也不会捕捉点击事件,但子组件可以捕获。
+- `'handled'`,当点击事件被子组件捕获时,键盘不会自动收起。这样切换 TextInput 时键盘可以保持状态。多数带有 TextInput 的情况下你应该选择此项。
+- `false`,已过时,请使用`'never'`代替。
+- `true`,已过时,请使用`'always'`代替。
+
+| 类型 | 默认值 |
+| --------------------------------------------------------- | --------- |
+| enum(`'always'`, `'never'`, `'handled'`, `false`, `true`) | `'never'` |
+
+---
+
+### `maintainVisibleContentPosition`
+
+当设置时,滚动视图将调整滚动位置,以便当前可见的第一个子元素在或超过 `minIndexForVisible` 时不会改变位置。这对于在两个方向上加载内容的列表非常有用,例如聊天线程,其中新消息可能会导致滚动位置跳跃。一个常见的值是 0,但其他值如 1 可以用于跳过加载指示器或其他不应保持位置的内容。
+
+可选的 `autoscrollToTopThreshold` 可以用于在调整后自动将内容滚动到顶部,如果用户在调整之前位于顶部阈值内。这对于聊天应用程序非常有用,其中您希望看到新消息滚动到位,但不会在用户已经向上滚动一段距离并且滚动一堆内容会变得混乱的情况下。
+
+注意事项一: 在启用此功能时重新排序滚动视图中的元素可能会导致跳跃和卡顿。可以修复,但目前没有计划这样做。目前,不要重新排序任何使用此功能的 ScrollViews 或 Lists。
+
+注意事项二: 此功能使用 `contentOffset` 和 `frame.origin` 在原生代码中计算可见性。遮挡、变换和其他复杂性不会被考虑在内,以确定内容是否“可见”。
+
+| 类型 |
+| ------------------------------------------------------------------------ |
+| object: `{minIndexForVisible: number, autoscrollToTopThreshold: number}` |
+
+---
+
+### `maximumZoomScale` iOS
+
+允许的最大缩放比例。默认值为 1.0。
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| number | `1.0` |
+
+---
+
+### `minimumZoomScale` iOS
+
+允许的最小缩放比例。默认值为 1.0。
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| number | `1.0` |
+
+---
+
+### `nestedScrollEnabled` Android
+
+在 Android API level 21(5.0)以上启用嵌套滚动。iOS 上默认支持嵌套滚动。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `onContentSizeChange`
+
+此函数会在 ScrollView 内部可滚动内容的视图发生变化时调用。
+
+调用参数为内容视图的宽和高: `(contentWidth, contentHeight)`。
+
+此方法是通过绑定在内容容器上的 onLayout 来实现的。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onMomentumScrollBegin`
+
+滚动动画开始时调用此函数。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onMomentumScrollEnd`
+
+滚动动画结束时调用此函数。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onScroll`
+
+在滚动的过程中,每帧最多调用一次此回调函数。调用的频率可以用`scrollEventThrottle`属性来控制。事件的构型如下(所有值都是数字):
+
+```js
+{
+ nativeEvent: {
+ contentInset: {bottom, left, right, top},
+ contentOffset: {x, y},
+ contentSize: {height, width},
+ layoutMeasurement: {height, width},
+ zoomScale
+ }
+}
+```
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onScrollBeginDrag`
+
+当用户开始拖动此视图时调用此函数。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onScrollEndDrag`
+
+当用户停止拖动此视图时调用此函数。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onScrollToTop` iOS
+
+当用户点击状态栏后,滚动视图滚动到顶部时调用此函数。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `overScrollMode`
+
+覆盖默认的 overScroll 模式
+
+可选的值有:
+
+- `'auto'` - 默认值,允许用户在内容超出视图高度之后可以滚动视图。
+- `'always'` - 无论内容尺寸,用户始终可以滚动视图。
+- `'never'` - 始终不允许用户滚动视图。
+
+| 类型 | 默认值 |
+| ------------------------------------- | -------- |
+| enum(`'auto'`, `'always'`, `'never'`) | `'auto'` |
+
+---
+
+### `pagingEnabled`
+
+当值为 true 时,滚动条会停在滚动视图的尺寸的整数倍位置。这个可以用在水平分页上。默认值为 false。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `persistentScrollbar` Android
+
+当滚动条不使用时,滚动条不会变透明。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `pinchGestureEnabled` iOS
+
+设置为 true 时,ScrollView 会允许用户使用双指缩放操作。默认值为 true。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `refreshControl`
+
+指定[RefreshControl](refreshcontrol.md)组件,用于为 ScrollView 提供下拉刷新功能。只能用于垂直视图,即`horizontal`不能为`true`。
+
+| 类型 |
+| ------- |
+| element |
+
+---
+
+### `removeClippedSubviews`
+
+(实验特性):当此属性为 true 时,屏幕之外的子视图(子视图的`overflow`样式需要设为`hidden`)会被移除。这个可以提升大列表的滚动性能。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `scrollEnabled`
+
+当值为 false 的时候,内容不能滚动,默认值为 true。
+
+注意即便禁止用户滚动,你也仍然可以调用`scrollTo`来滚动。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `scrollEventThrottle`
+
+限制滚动事件的触发频率,指定为毫秒时间间隔。这在响应滚动时执行昂贵操作时非常有用。值 ≤ `16` 将禁用节流,无论设备的刷新率如何。
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| number | `0` |
+
+---
+
+### `scrollIndicatorInsets` iOS
+
+滚动视图指示器距离视图边缘的距离。通常应设置为与 `contentInset` 相同的值。
+
+| 类型 | 默认值 |
+| -------------------------------------------------------------------- | ---------------------------------------- |
+| object: `{top: number, left: number, bottom: number, right: number}` | `{top: 0, left: 0, bottom: 0, right: 0}` |
+
+---
+
+### `scrollPerfTag` Android
+
+用于记录此滚动视图的滚动性能。会强制开启动量事件(见 sendMomentumEvents)。这不会在默认情况下做任何事情,你需要实现一个自定义的 native FpsListener 才能使其有用。
+
+| 类型 |
+| ------ |
+| string |
+
+---
+
+### `scrollToOverflowEnabled` iOS
+
+当值为 true 时,滚动视图可以被编程地滚动超过其内容大小。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `scrollsToTop` iOS
+
+当值为 true 时,点击状态栏的时候视图会滚动到顶部。默认值为 true。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `showsHorizontalScrollIndicator`
+
+当此属性为 `true` 的时候,显示一个水平方向的滚动条。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `showsVerticalScrollIndicator`
+
+当此属性为 `true` 的时候,显示一个垂直方向的滚动条。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `snapToAlignment` iOS
+
+当设置了 `snapToInterval` 时,`snapToAlignment` 会定义停驻点与滚动视图之间的关系。
+
+可能的值有:
+
+- `'start'` 会将停驻点对齐在左侧(水平)或顶部(垂直)。
+- `'center'` 会将停驻点对齐到中间。
+- `'end'` 会将停驻点对齐到右侧(水平)或底部(垂直)。
+
+| 类型 | 默认值 |
+| ------------------------------------ | --------- |
+| enum(`'start'`, `'center'`, `'end'`) | `'start'` |
+
+---
+
+### `snapToEnd`
+
+当设置了 `snapToOffsets` 时,默认情况下,列表的末尾被视为一个停驻点。设置 `snapToEnd` 为 `false` 以禁用此行为并允许列表在它的末尾和最后一个 `snapToOffsets` 偏移量之间自由滚动。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `snapToInterval`
+
+当设置时,会让滚动视图停止在 `snapToInterval` 的倍数的位置。这可以在一些子视图比滚动视图本身小的时候用于实现分页显示。需要与 `snapToAlignment` 组合使用。通常与 `decelerationRate="fast"` 一起使用。覆盖较不配置的 `pagingEnabled` 属性。
+
+| 类型 |
+| ------ |
+| number |
+
+---
+
+### `snapToOffsets`
+
+当设置时,会让滚动视图停止在定义的偏移量处。这可以在一些子视图比滚动视图本身小的时候用于实现分页显示。通常与 `decelerationRate="fast"` 一起使用。覆盖较不配置的 `pagingEnabled` 和 `snapToInterval` 属性。
+
+| 类型 |
+| ------------------ |
+| 以数字为元素的数组 |
+
+---
+
+### `snapToStart`
+
+当设置了 `snapToOffsets` 时,默认情况下,列表的开始被视为一个停驻点。设置 `snapToStart` 为 `false` 以禁用此行为并允许列表在它的开始和第一个 `snapToOffsets` 偏移量之间自由滚动。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `StickyHeaderComponent`
+
+一个 React 组件,用于渲染粘性头部,应与 `stickyHeaderIndices` 一起使用。如果粘性头部使用自定义变换,例如,当您希望列表具有可动画化和可隐藏的头部时,可能需要设置此组件。如果未提供组件,将使用默认的 [`ScrollViewStickyHeader`](https://github.com/facebook/react-native/blob/main/packages/react-native/Libraries/Components/ScrollView/ScrollViewStickyHeader.js) 组件。
+
+| 类型 |
+| ------------------ |
+| component, element |
+
+---
+
+### `stickyHeaderHiddenOnScroll`
+
+当设置为 `true` 时,粘性头部将在向下滚动列表时隐藏,当向上滚动时,它将固定在列表顶部。
+
+| 类型 | 默认值 |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `stickyHeaderIndices`
+
+一个子视图下标的数组,用于决定哪些成员会在滚动之后固定在屏幕顶端。举个例子,传递`stickyHeaderIndices={[0]}`会让第一个成员固定在滚动视图顶端。这个属性不能和`horizontal={true}`一起使用。
+
+| 类型 |
+| ------------------ |
+| 以数字为元素的数组 |
+
+---
+
+### `zoomScale` iOS
+
+当前滚动视图内容的缩放比例。
+
+| 类型 | 默认值 |
+| ------ | ------ |
+| number | `1.0` |
+
+---
+
+## 方法
+
+### `flashScrollIndicators()`
+
+```tsx
+flashScrollIndicators();
+```
+
+短暂地显示滚动指示器。
+
+---
+
+### `scrollTo()`
+
+```tsx
+scrollTo(
+ options?: {x?: number, y?: number, animated?: boolean} | number,
+ deprecatedX?: number,
+ deprecatedAnimated?: boolean,
+);
+```
+
+滚动到指定的 x, y 偏移处。第三个参数为是否启用平滑滚动动画。
+
+示例:
+
+`scrollTo({x: 0, y: 0, animated: true})`
+
+---
+
+### `scrollToEnd()`
+
+```tsx
+scrollToEnd(options?: {animated?: boolean});
+```
+
+滚动到视图底部(水平方向的视图则滚动到最右边)。
+
+加上动画参数`scrollToEnd({animated: true})`则启用平滑滚动动画,或是调用`scrollToEnd({animated: false})`来立即跳转。如果不使用参数,则`animated`选项默认启用。
+
+---
diff --git a/cnwebsite/versioned_docs/version-0.85/sectionlist.md b/cnwebsite/versioned_docs/version-0.85/sectionlist.md
new file mode 100644
index 00000000000..6fd98c15047
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/sectionlist.md
@@ -0,0 +1,370 @@
+---
+id: sectionlist
+title: SectionList
+---
+
+高性能的分组(section)列表组件,支持下面这些常用的功能:
+
+- 完全跨平台。
+- 行组件显示或隐藏时可配置回调事件。
+- 支持单独的头部组件。
+- 支持单独的尾部组件。
+- 支持自定义行间分隔线。
+- 支持分组的头部组件。
+- 支持分组的分隔线。
+- 支持多种数据源结构
+- 支持下拉刷新。
+- 支持上拉加载。
+
+如果你的列表不需要分组(section),那么可以使用结构更简单的[``](flatlist.md)。
+
+## 示例
+
+```SnackPlayer name=SectionList%20Example
+import React from 'react';
+import {StyleSheet, Text, View, SectionList, StatusBar} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const DATA = [
+ {
+ title: 'Main dishes',
+ data: ['Pizza', 'Burger', 'Risotto'],
+ },
+ {
+ title: 'Sides',
+ data: ['French Fries', 'Onion Rings', 'Fried Shrimps'],
+ },
+ {
+ title: 'Drinks',
+ data: ['Water', 'Coke', 'Beer'],
+ },
+ {
+ title: 'Desserts',
+ data: ['Cheese Cake', 'Ice Cream'],
+ },
+];
+
+const App = () => (
+
+
+ item + index}
+ renderItem={({item}) => (
+
+ {item}
+
+ )}
+ renderSectionHeader={({section: {title}}) => (
+ {title}
+ )}
+ />
+
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ paddingTop: StatusBar.currentHeight,
+ marginHorizontal: 16,
+ },
+ item: {
+ backgroundColor: '#f9c2ff',
+ padding: 20,
+ marginVertical: 8,
+ },
+ header: {
+ fontSize: 32,
+ backgroundColor: '#fff',
+ },
+ title: {
+ fontSize: 24,
+ },
+});
+
+export default App;
+```
+
+本组件实质是基于[``](virtualizedlist.md)组件的封装,继承了其所有 props(也包括所有[``](scrollview.md))的 props)。此外还有下面这些需要注意的事项:
+
+- 当某行滑出渲染区域之外后,其内部状态将不会保留。请确保你在行组件以外的地方保留了数据。
+- 本组件继承自`PureComponent`而非通常的`Component`,这意味着如果其`props`在`浅比较`中是相等的,则不会重新渲染。所以请先检查你的`renderItem`函数所依赖的`props`数据(包括`data`属性以及可能用到的父组件的 state),如果是一个引用类型(Object 或者数组都是引用类型),则需要先修改其引用地址(比如先复制到一个新的 Object 或者数组中),然后再修改其值,否则界面很可能不会刷新。(译注:这一段不了解的朋友建议先学习下[js 中的基本类型和引用类型](https://segmentfault.com/a/1190000002789651)。)
+- 为了优化内存占用同时保持滑动的流畅,列表内容会在屏幕外异步绘制。这意味着如果用户滑动的速度超过渲染的速度,则会先看到空白的内容。这是为了优化不得不作出的妥协,而我们也在设法持续改进。
+- 默认情况下每行都需要提供一个不重复的 key 属性。你也可以提供一个`keyExtractor`函数来生成 key。
+
+---
+
+# 文档
+
+## Props
+
+继承了所有的[ScrollView Props](scrollview.md#props).
+
+### `sections`
+
+用来渲染的数据,类似于[FlatList](flatlist.md)中的`data`属性。
+
+| 类型 | 必需 |
+| ------------------------------------------- | ---- |
+| array of [Section](sectionlist.md#section)s | 是 |
+
+---
+
+### `initialNumToRender`
+
+指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户呈现可见的内容。注意这第一批次渲染的元素不会在滑动过程中被卸载,这样是为了保证用户执行返回顶部的操作时,不需要重新渲染首批元素。
+
+| 类型 | 必需 |
+| ------ | ---- |
+| number | 否 |
+
+---
+
+### `keyExtractor`
+
+此函数用于为给定的 item 生成一个不重复的 key。Key 的作用是使 React 能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。若不指定此函数,则默认抽取 item.key 作为 key 值。若 item.key 也不存在,则使用数组下标。注意这只设置了每行(item)的 key,对于每个组(section)仍然需要另外设置 key。
+
+| 类型 | 必需 |
+| ------------------------------------- | ---- |
+| (item: Item, index: number) => string | 是 |
+
+---
+
+### 必需
**`renderItem`**
+
+用来渲染每一个 section 中的每一个列表项的默认渲染器。可以在 section 级别上进行覆盖重写。必须返回一个 react 组件。
+
+| 类型 |
+| ---- |
+| 函数 |
+
+渲染函数将传递一个带有以下键的对象:
+
+- `item`(对象) - 此部分`data`键中指定的项目对象
+- `index`(数字) - 该项在部分内的索引。
+- `section`(对象) - 指定为`sections`中完整的部分对象。
+- `separators`(对象) - 一个具有以下键的对象:
+ - `highlight`(函数) - `() => void`
+ - `unhighlight`(函数) - `() => void`
+ - `updateProps`(函数) - `(select, newProps) => void`
+ - `select` (枚举值)- 可能值为`leading`,`trailing`
+ - `newProps` (对象)
+
+---
+
+### `extraData`
+
+如果有除`data`以外的数据用在列表中(不论是用在`renderItem`还是 Header 或者 Footer 中),请在此属性中指定。同时此数据在修改时也需要先修改其引用地址(比如先复制到一个新的 Object 或者数组中),然后再修改其值,否则界面很可能不会刷新。
+
+| 类型 | 必需 |
+| ---- | ---- |
+| any | 否 |
+
+---
+
+### `ItemSeparatorComponent`
+
+行与行之间的分隔线组件。不会出现在第一行之前和最后一行之后。By default, `highlighted`, `section`, and `[leading/trailing][Item/Separator]` props are provided. `renderItem` provides `separators.highlight`/`unhighlight` which will update the `highlighted` prop, but you can also add custom props with `separators.updateProps`.
+
+| 类型 | 必需 |
+| ------------------------------ | ---- |
+| [component, function, element] | 否 |
+
+---
+
+### `inverted`
+
+翻转滚动方向。实质是将 scale 变换设置为-1。
+
+| 类型 | 必需 |
+| --------- | ---- |
+| [boolean] | 否 |
+
+---
+
+### `ListFooterComponent`
+
+尾部组件。
+
+| 类型 | 必需 |
+| ------------------------------ | ---- |
+| [component, function, element] | 否 |
+
+---
+
+### `ListEmptyComponent`
+
+当列表数据为空时渲染的组件。
+
+| 类型 | 必需 |
+| ------------------------------ | ---- |
+| [component, function, element] | 否 |
+
+---
+
+### `onEndReachedThreshold`
+
+决定当距离内容最底部还有多远时触发`onEndReached`回调。注意此参数是一个比值而非像素单位。比如,0.5 表示距离内容最底部的距离为当前列表可见长度的一半时触发。
+
+| 类型 | 必需 |
+| -------- | ---- |
+| [number] | 否 |
+
+---
+
+### `onRefresh`
+
+如果设置了此选项,则会在列表头部添加一个标准的[`RefreshControl`](refreshcontrol.md)控件,以便实现“下拉刷新”的功能。同时你需要正确设置`refreshing`属性。如果你想把刷新控件往下移动一些(比如 100 个 pt),可以设置`progressViewOffset={100}`。
+
+| 类型 | 必需 |
+| ------------ | ---- |
+| [() => void] | 否 |
+
+---
+
+### `onViewableItemsChanged`
+
+当行的可见性发生变化时调用,根据`viewabilityConfig`属性定义。
+
+| 类型 |
+| ----------------------------------------------------------------------------------------------------- |
+| `md (callback: {changed: [ViewToken](viewtoken)[], viewableItems: [ViewToken](viewtoken)[]}) => void` |
+
+---
+
+### `refreshing`
+
+在等待加载新数据时将此属性设为 true,列表就会显示出一个正在加载的符号。
+
+| 类型 | 必需 |
+| --------- | ---- |
+| [boolean] | 否 |
+
+---
+
+### `removeClippedSubviews`
+
+Note: may have bugs (missing content) in some circumstances - use at your own risk.
+
+This may improve scroll performance for large lists.
+
+| 类型 | 必需 |
+| ------- | ---- |
+| boolean | 否 |
+
+---
+
+### `ListHeaderComponent`
+
+头部组件。
+
+| 类型 | 必需 |
+| ---------------------------- | ---- |
+| component, function, element | 否 |
+
+---
+
+### `renderSectionFooter`
+
+每个组的尾部组件。
+
+| Type |
+| ------------------------------------------------------------------------- |
+| `md (info: {section: [Section](sectionlist#section)}) => element | null` |
+
+---
+
+### `renderSectionHeader`
+
+在每个 section 的头部渲染。在 iOS 上,这些 headers 是默认粘接在`ScrollView`的顶部的. 参见[`stickySectionHeadersEnabled`](#stickySectionHeadersEnabled)。
+
+| Type |
+| ------------------------------------------------------------------------- |
+| `md (info: {section: [Section](sectionlist#section)}) => element | null` |
+
+---
+
+### `SectionSeparatorComponent`
+
+在每个`section`的顶部和底部渲染(区别于`ItemSeparatorComponent`,它仅在列表项之间渲染)。它的作用是为了从视觉上把`section`与它上方或下方的`headers`区别开来,从这个意义上讲,它的作用和`ItemSeparatorComponent`是一样的. 它也接受`highlighted`, `[leading/trailing][Item/Separator]`这两个默认提供的属性或其他通过`separators.updateProps`添加的自定义属性.
+
+| Type |
+| ---------------------------- |
+| component, element, function |
+
+---
+
+### `stickySectionHeadersEnabled`
+
+当下一个 section 把它的前一个 section 的可视区推离屏幕的时候,让这个 section 的 header 粘连在屏幕的顶端。这个属性在 iOS 上是默认可用的,因为这是 iOS 的平台规范。
+
+| 类型 | 必需 |
+| ------- | ---- |
+| boolean | 否 |
+
+## 方法
+
+### `scrollToLocation()`
+
+```jsx
+scrollToLocation(params);
+```
+
+将可视区内位于特定`sectionIndex` 或 `itemIndex` (section 内)位置的列表项,滚动到可视区的制定位置。比如说,`viewPosition` 为 0 时将这个列表项滚动到可视区顶部 (可能会被顶部粘接的 header 覆盖), 为 1 时将它滚动到可视区底部, 为 0.5 时将它滚动到可视区中央。
+
+> 注意: 如果没有设置`getItemLayout`或是`onScrollToIndexFailed`,就不能滚动到位于外部渲染区的位置。
+
+**参数:**
+
+| 名称 | 类型 | 必需 | 说明 |
+| ------ | ------ | ---- | ------------ |
+| params | object | 是 | 看下面的说明 |
+
+Valid `params` keys are:
+
+- 'animated' (boolean) - Whether the list should do an animation while scrolling. Defaults to `true`.
+- 'itemIndex' (number) - Index within section for the item to scroll to. Required.
+- 'sectionIndex' (number) - Index for section that contains the item to scroll to. Required.
+- 'viewOffset' (number) - 一个以像素为单位,到最终位置偏移距离的固定值,比如为了弥补粘接的 header 所占据的空间。
+- 'viewPosition' (number) - A value of `0` places the item specified by index at the top, `1` at the bottom, and `0.5` centered in the middle.
+
+---
+
+### `recordInteraction()`
+
+```jsx
+recordInteraction();
+```
+
+主动通知列表发生了一个事件,以使列表重新计算可视区域。比如说当`waitForInteractions` 为 true 并且用户没有滚动列表时,就可以调用这个方法。不过一般来说,当用户点击了一个列表项,或发生了一个导航动作时,我们就可以调用这个方法。
+
+---
+
+### `flashScrollIndicators()`
+
+```jsx
+flashScrollIndicators();
+```
+
+短暂地显示滚动指示器。
+
+## 类型定义
+
+### Section
+
+An object that identifies the data to be rendered for a given section.
+
+| 类型 |
+| ---- |
+| any |
+
+**属性:**
+
+| 名称 | 类型 | 说明 |
+| ------------------------ | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| data | array | The data for rendering items in this section. Array of objects, much like [`FlatList`的 data 属性](flatlist.md#data). |
+| [key] | string | Optional key to keep track of section re-ordering. If you don't plan on re-ordering sections, the array index will be used by default. |
+| [renderItem] | function | Optionally define an arbitrary item renderer for this section, overriding the default [`renderItem`](sectionlist.md#renderitem) for the list. |
+| [ItemSeparatorComponent] | component, function, element | Optionally define an arbitrary item separator for this section, overriding the default [`ItemSeparatorComponent`](sectionlist.md#itemseparatorcomponent) for the list. |
+| [keyExtractor] | function | Optionally define an arbitrary key extractor for this section, overriding the default [`keyExtractor`](sectionlist.md#keyextractor). |
diff --git a/cnwebsite/versioned_docs/version-0.85/security.md b/cnwebsite/versioned_docs/version-0.85/security.md
new file mode 100644
index 00000000000..f5ae5724bf6
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/security.md
@@ -0,0 +1,125 @@
+---
+id: security
+title: 网络安全策略
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+开发应用时安全常常是一个被忽视的话题。的确,搭建一个完全无懈可击的软件是不可能的——我们还没有发明一个完全坚不可摧的锁(毕竟,银行金库已经足够坚固但仍然会被闯入)。然而,遭受恶意攻击或暴露安全漏洞的可能性与您愿意投入保护应用程序免受此类事件的努力成反比。尽管普通的挂锁可以被撬开,但它仍然比橱柜挂钩更难攻破!
+
+
+
+在本指南中,您将了解到存储敏感信息、认证、网络安全的最佳实践以及可以帮助您保护应用程序的工具。这不是一个飞行前检查清单——这是一个选项目录,每一个选项都将有助于进一步保护您的应用程序和用户。
+
+## 保存敏感信息
+
+永远不要在应用代码中存储敏感的API密钥。任何包含在您的代码中的内容都可能被任何人以明文形式访问,只要他们检查了应用包。像[react-native-dotenv](https://github.com/goatandsheep/react-native-dotenv)和[react-native-config](https://github.com/luggit/react-native-config/)这样的工具非常适合添加环境特定的变量,比如API端点,但它们不应该与服务器端的环境变量混淆,后者通常可以包含秘密和API密钥。
+
+如果你的应用需要使用API密钥或秘密来访问某些资源,最安全的处理方式是在应用和资源之间构建一个编排层。这可以是一个无服务器函数(例如使用AWS Lambda或Google Cloud Functions),它可以转发带有所需API密钥或秘密的请求。服务器端代码中的秘密不能像应用代码中的秘密那样被API消费者访问。
+
+**对于持久化用户数据,请根据其敏感性选择合适的存储类型。** 随着你的应用程序的使用,你经常会发现需要在设备上保存数据,无论是为了支持应用程序离线使用、减少网络请求还是保存用户在会话之间的访问令牌,这样他们就不必每次使用应用程序时都重新认证。
+
+:::info
+**持久化与非持久化** —— 持久化数据被写入设备的内存中,这允许数据在应用程序启动后由你的应用程序读取而无需再次进行网络请求以获取它或要求用户重新输入它。但这也可能使这些数据更容易被攻击者访问。非持久化数据从未被写入内存——所以没有可访问的数据!
+:::
+
+### Async Storage
+
+[Async Storage](https://github.com/react-native-async-storage/async-storage) 是一个由社区维护的 React Native 模块,它提供了一个异步、未加密的键值对存储。异步存储不是在应用之间共享的:每个应用都有自己的沙盒环境,并且无法访问其他应用的数据。
+
+| **使用Async Storage的情况** | **不推荐使用Async Storage的情况** |
+| ------------------------------ | --------------------------------- |
+| 在应用运行间持久保存非敏感数据 | 令牌存储 |
+| 持久保存 Redux 状态 | 密钥 |
+| 持久保存 GraphQL 状态 | |
+
+:::note
+Async Storage 是 React Native 中与 Web 的 Local Storage 类似的功能
+:::
+
+### 安全存储
+
+React Native 本身没有提供任何用于安全地储存敏感数据的方式。然而,对于 Android 和 iOS 平台来说,已经有现成的解决方案。
+
+#### iOS - Keychain Services
+
+[Keychain Services](https://developer.apple.com/documentation/security/keychain_services)允许你安全地为用户储存少量敏感信息。这是存放证书、令牌、密码以及任何不应该放在 Async Storage 中的其他敏感信息的理想场所。
+
+#### Android - Secure Shared Preferences
+
+[Shared Preferences](https://developer.android.com/reference/android/content/SharedPreferences)是 Android 上的一个持久化键值对数据仓库。默认情况下,在 Shared Preferences 中的数据**不会被加密**,但是 [Encrypted Shared Preferences](https://developer.android.com/topic/security/data) 对于 Android 的 Shared Preferences 类进行了封装,并自动加密了键和值。
+
+#### Android - Keystore
+
+[Android Keystore](https://developer.android.com/training/articles/keystore)系统允许您将加密密钥存储在容器中,使其更难以从设备中提取。
+
+为了使用iOS Keychain服务或Android Secure Shared Preferences,您可以自己编写一个桥接程序,或者使用一个库来为您包装它们,并提供统一的API供您自行承担风险。以下是一些值得考虑的库:
+
+- [expo-secure-store](https://docs.expo.dev/versions/latest/sdk/securestore/)
+- [react-native-keychain](https://github.com/oblador/react-native-keychain)
+
+:::warning Caution
+**请注意不要无意中存储或暴露敏感信息。**这可能会意外发生,例如在redux状态中保存敏感表单数据并持久化整个状态树到Async Storage。或者将用户令牌和个人信息发送到应用程序监控服务如Sentry或Crashlytics。
+:::
+
+## 认证和深度链接(Deep Linking)
+
+
+
+移动应用程序有一个独特的漏洞,这在网络中是不存在的:**深度链接**。深度链接是一种将数据直接发送到原生应用程序的方式,来自外部来源。一个深度链接看起来像 `app://` ,其中 `app` 是您的应用方案,//后面的任何内容都可能被内部用来处理请求。
+
+例如,如果您正在构建一个电子商务应用程序,您可以使用 `app://products/1` 来深入链接到您的应用程序,并打开具有id为1的产品的详细页面。您可以将这些视为网络上的URLs,但有一个关键的区别:
+深度链接是不安全的,您永远不应该在它们中发送任何敏感信息。
+
+深度链接不安全的原因是因为没有集中的方法注册URL方案。作为一个应用开发者,您可以通过 [在Xcode中配置它](https://developer.apple.com/documentation/uikit/inter-process_communication/allowing_apps_and_websites_to_link_to_your_content/defining_a_custom_url_scheme_for_your_app) 对于iOS或[在Android上添加意图](https://developer.android.com/training/app-links/deep-linking)来使用几乎任何您选择的url方案。
+
+没有什么可以阻止恶意应用通过也注册相同的计划并随后获取包含的数据来劫持您的深层连接。发送像 `app://products/1` 的东西并没有什么害处,但发送令牌会是一个安全问题。
+
+当操作系统在打开链接时有两个或更多应用程序可供选择时,Android会向用户显示一个模态框并询问他们使用哪个应用程序来打开链接。然而,在iOS上,操作系统将为您做出选择,因此用户将毫无察觉。苹果公司已经在后来的iOS版本(iOS 11)中采取了措施来解决这个问题,其中他们实施了一个先到先服务的原则,尽管这个漏洞仍然可以以不同的方式被利用,你可以在[这里](https://thehackernews.com/2019/07/ios-custom-url-scheme.html)阅读更多相关内容。使用[通用链接](https://developer.apple.com/ios/universal-links/)将允许您安全地在iOS内连接到您的应用内容。
+
+### OAuth2 和重定向
+
+OAuth2 认证协议现在非常流行,被誉为最完整和安全的协议之一. OpenID Connect 协议也是基于此构建的. 在 OAuth2 中, 用户需要通过第三方进行身份验证. 成功完成后, 第三方会带着一个验证码重新定向回请求的应用, 这个验证码可以用来交换 JWT - 即JSON Web Token。
+
+在网上这一步是安全的因为网上的URL保证是唯一的. 对于应用来说却并非如此,因为如前所述没有统一的方法去注册URL方案!为了解决这个安全隐患必须增加额外的一个检查步骤叫做 PKCE.
+
+[PKCE](https://oauth.net/2/pkce/)发音为“Pixy”代表Proof of Key Code Exchange,是对OAuth 2规范的一个扩展。这涉及到增加了一层安全措施,用来验证身份验证和令牌交换请求来自同一个客户端。PKCE使用了SHA256加密哈希算法。SHA256 为任意大小的文字或者文件创建了一个独特的“签名”,但它:
+
+- 不管输入文件的大小总是保持一致的长度
+- 对同样的输入始终产生一样的结果
+- 是单向的(也就是说你不可以通过它反向工程出原始输入)
+
+现在你有这两个值:
+
+- **code_verifier** -由客户端生成的大随机字符串
+- **code_challenge** - code_verifier 的 SHA256
+
+在初始的 `/authorize` 请求期间,客户端还会发送它保存在内存中的 `code_verifier` 对应的 `code_challenge`。授权请求正确返回后,客户端还会发送用于生成 `code_challenge` 的 `code_verifier`。身份提供商(IDP)随后会计算 `code_challenge`,检查它是否与最初的 `/authorize` 请求中设置的值匹配,并仅在值匹配时才发送访问令牌。
+
+这保证了只有触发初始授权流程的应用才能成功地将验证码交换为 JWT。因此,即使恶意应用获得了验证码,它本身也是无用的。要查看这个过程的实际演示,请查看 [这个示例](https://aaronparecki.com/oauth-2-simplified/#mobile-apps)。
+
+考虑用于原生 OAuth 的库是 [react-native-app-auth](https://github.com/FormidableLabs/react-native-app-auth)。React-native-app-auth 是一个与 OAuth2 提供商通信的 SDK。它封装了原生的 [AppAuth-iOS](https://github.com/openid/AppAuth-iOS) 和 [AppAuth-Android](https://github.com/openid/AppAuth-Android) 库,并可以支持 PKCE。
+
+:::note
+React-native-app-auth 只有在您的身份提供商支持 PKCE 时才能支持它。
+:::
+
+
+
+## 网络安全
+
+您的 API 应该始终使用[SSL加密](https://www.ssl.com/faqs/faq-what-is-ssl/)。SSL加密可以防止请求的数据在离开服务器后、到达客户端之前以明文形式被读取。您可以通过端点以`https://`而不是`http://`开头来判断它是安全的。
+
+### SSL 固定
+
+即使使用HTTPS端点,您的数据仍然可能容易受到拦截的威胁。在HTTPS中,只有当服务器能够提供由预装在客户端上的可信证书颁发机构签名的有效证书时,客户端才会信任该服务器。攻击者可以利用这一点,在用户的设备上安装恶意根CA证书,这样客户端就会信任所有由攻击者签名的证书。因此,仅依赖于证书本身仍可能使您容易受到[中间人攻击](https://en.wikipedia.org/wiki/Man-in-the-middle_attack)。
+
+**SSL固定**是一种可以在客户端使用的技巧来避免这种攻击。它的工作原理是在开发期间将受信任的证书列表嵌入(或固定)到客户端中,以便只接受用其中一个受信任的证书签名的请求,并拒绝任何自签名的证书。
+
+:::warning Caution
+使用SSL固定时,您应该注意到期日期的问题。每1-2年就需要更新一次数字认证书,在数字认证书过期之后需要同时更新应用程序和服务器上的版本信息。一旦服务器上的数字认证书得到更新,则那些内嵌有旧版数字认证书的应用将无法正常工作了。
+:::
+
+## 小结
+
+没有绝对安全的方法来处理安全性问题,但通过有意识的努力和勤奋,可以显著降低应用程序中安全漏洞的可能性。根据存储在您的应用程序中的数据的敏感性、用户数量以及黑客获得访问权限时可能造成的损害,相应地投资于安全性。并记住:从未首先请求的信息更难被获取。
diff --git a/cnwebsite/versioned_docs/version-0.85/segmentedcontrolios.md b/cnwebsite/versioned_docs/version-0.85/segmentedcontrolios.md
new file mode 100644
index 00000000000..7a878b2439e
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/segmentedcontrolios.md
@@ -0,0 +1,10 @@
+---
+id: segmentedcontrolios
+title: '❌ SegmentedControlIOS'
+---
+
+:::danger 已从 React Native 中移除
+请使用[社区包](https://reactnative.directory/?search=segmentedcontrol)替代。
+:::
+
+---
diff --git a/cnwebsite/versioned_docs/version-0.85/set-up-your-environment.md b/cnwebsite/versioned_docs/version-0.85/set-up-your-environment.md
new file mode 100644
index 00000000000..88d96930a8c
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/set-up-your-environment.md
@@ -0,0 +1,108 @@
+---
+id: set-up-your-environment
+title: 搭建开发环境
+hide_table_of_contents: true
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+import constants from '@site/core/TabsConstants';
+
+import GuideLinuxAndroid from './\_getting-started-linux-android.md';
+import GuideMacOSAndroid from './\_getting-started-macos-android.md';
+import GuideWindowsAndroid from './\_getting-started-windows-android.md';
+import GuideMacOSIOS from './\_getting-started-macos-ios.md';
+
+本指南将帮助你搭建开发环境,以便使用 Android Studio 和 Xcode 运行你的项目。这样你就可以使用 Android 模拟器和 iOS 模拟器进行开发、在本地构建应用等。
+
+:::info
+本指南需要安装 Android Studio 或 Xcode。如果你已经安装了其中一个,通常几分钟内即可上手。如果尚未安装,预计需要大约一个小时来完成安装和配置。
+
+
+搭建环境是必须的吗?
+
+如果你使用的是[框架](/architecture/glossary#react-native-framework),则不需要搭建开发环境。使用 React Native 框架时,框架会自动为你构建原生应用,无需你手动安装 Android Studio 或 Xcode。
+
+如果你有特殊限制无法使用框架,或者你希望编写自己的框架,那么搭建本地环境是必需的。环境搭建完成后,请参阅[不使用框架开始开发](getting-started-without-a-framework)。
+
+
+:::
+
+#### 开发操作系统
+
+
+
+
+#### 目标操作系统
+
+
+
+
+[//]: # 'macOS, Android'
+
+
+
+
+
+
+[//]: # 'macOS, iOS'
+
+
+
+
+
+
+
+
+
+#### 目标操作系统
+
+
+
+
+[//]: # 'Windows, Android'
+
+
+
+
+
+
+[//]: # 'Windows, iOS'
+
+## 不支持
+
+:::info
+构建 iOS 原生代码项目需要 Mac。你可以使用 [Expo](environment-setup#start-a-new-react-native-project-with-expo) 提供的 [Expo Go](https://expo.dev/go) 在你的 iOS 设备上开发应用。
+:::
+
+
+
+
+
+
+
+#### 目标操作系统
+
+
+
+
+[//]: # 'Linux, Android'
+
+
+
+
+
+
+[//]: # 'Linux, iOS'
+
+## 不支持
+
+:::info
+构建 iOS 原生代码项目需要 Mac。你可以使用 [Expo](environment-setup#start-a-new-react-native-project-with-expo) 提供的 [Expo Go](https://expo.dev/go) 在你的 iOS 设备上开发应用。
+:::
+
+
+
+
+
+
diff --git a/cnwebsite/versioned_docs/version-0.85/settings.md b/cnwebsite/versioned_docs/version-0.85/settings.md
new file mode 100644
index 00000000000..82a7b64a07e
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/settings.md
@@ -0,0 +1,103 @@
+---
+id: settings
+title: Settings
+---
+
+`Settings`是对[`NSUserDefaults`](https://developer.apple.com/documentation/foundation/nsuserdefaults)的封装。它是iOS平台上的一种持久的键值对存储。
+
+## 示例
+
+```SnackPlayer name=Settings%20Example&supportedPlatforms=ios
+import React, {useState} from 'react';
+import {Button, Settings, StyleSheet, Text} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ const [data, setData] = useState(() => Settings.get('data'));
+
+ return (
+
+
+ Stored value:
+ {data}
+ {
+ Settings.set({data: 'React'});
+ setData(Settings.get('data'));
+ }}
+ title="Store 'React'"
+ />
+ {
+ Settings.set({data: 'Native'});
+ setData(Settings.get('data'));
+ }}
+ title="Store 'Native'"
+ />
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ },
+ value: {
+ fontSize: 24,
+ marginVertical: 12,
+ },
+});
+
+export default App;
+```
+
+---
+
+# Reference
+
+## Methods
+
+### `clearWatch()`
+
+```tsx
+static clearWatch(watchId: number);
+```
+
+`watchId` is the number returned by `watchKeys()` when the subscription was originally configured.
+
+---
+
+### `get()`
+
+```tsx
+static get(key: string): any;
+```
+
+Get the current value for a given `key` in `NSUserDefaults`.
+
+---
+
+### `set()`
+
+```tsx
+static set(settings: Record);
+```
+
+Set one or more values in `NSUserDefaults`.
+
+---
+
+### `watchKeys()`
+
+```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.
+
+:::note
+`watchKeys()` by design ignores internal `set()` calls and fires callback only on changes preformed outside of React Native code.
+:::
diff --git a/cnwebsite/versioned_docs/version-0.85/shadow-props.md b/cnwebsite/versioned_docs/version-0.85/shadow-props.md
new file mode 100644
index 00000000000..3840211f420
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/shadow-props.md
@@ -0,0 +1,285 @@
+---
+id: shadow-props
+title: Shadow Props
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+
+
+
+```SnackPlayer name=Shadow%20Props&supportedPlatforms=ios&ext=js&dependencies=@react-native-community/slider
+import React, {useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+import Slider from '@react-native-community/slider';
+
+const ShadowPropSlider = ({label, value, ...props}) => {
+ 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;
+```
+
+
+
+
+```SnackPlayer name=Shadow%20Props&supportedPlatforms=ios&ext=tsx&dependencies=@react-native-community/slider
+import React, {useState} from 'react';
+import {Text, View, StyleSheet} from 'react-native';
+import Slider, {SliderProps} from '@react-native-community/slider';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+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;
+```
+
+
+
+
+---
+
+# 参考
+
+React Native 中有 3 组阴影 API:
+
+- `boxShadow`:一个 View 样式属性,是 Web 同名[样式属性](https://developer.mozilla.org/zh-CN/docs/Web/CSS/box-shadow)的规范兼容实现。
+- `dropShadow`:作为 [`filter`](./view-style-props#filter) View 样式属性一部分提供的特定滤镜函数。
+- 各种 `shadow` 属性(`shadowColor`、`shadowOffset`、`shadowOpacity`、`shadowRadius`):直接映射到平台级 API 暴露的原生对应属性。
+
+`dropShadow` 和 `boxShadow` 的区别如下:
+
+- `dropShadow` 作为 `filter` 的一部分存在,而 `boxShadow` 是独立的样式属性。
+- `dropShadow` 是 alpha 遮罩,因此只有 alpha 值大于 0 的像素才会"投射"阴影。`boxShadow` 会围绕元素的边框盒投射阴影,无论其内容如何(除非设置了 inset)。
+- `dropShadow` 仅在 Android 上可用,`boxShadow` 在 iOS 和 Android 上都可用。
+- `dropShadow` 不能像 `boxShadow` 那样设置为 inset(内阴影)。
+- `dropShadow` 没有像 `boxShadow` 那样的 `spreadDistance` 参数。
+
+`boxShadow` 和 `dropShadow` 通常比 `shadow` 属性功能更强大。但 `shadow` 属性直接映射到原生平台级 API,因此如果你只需要简单的阴影效果,推荐使用这些属性。注意只有 `shadowColor` 同时在 Android 和 iOS 上生效,其他 `shadow` 属性仅在 iOS 上生效。
+
+## Props
+
+### `boxShadow`
+
+参见 [View 样式属性](./view-style-props#boxshadow) 文档。
+
+### `dropShadow` Android
+
+参见 [View 样式属性](./view-style-props#filter) 文档。
+
+### `shadowColor`
+
+设置阴影颜色。
+
+此属性仅在 Android API 28 及以上版本生效。对于更低版本的 Android API,请使用 [`elevation` 属性](view-style-props#elevation-android) 实现类似功能。
+
+| 类型 |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `shadowOffset` iOS
+
+设置阴影偏移量。
+
+| 类型 |
+| ---------------------------------------- |
+| object: `{width: number,height: number}` |
+
+---
+
+### `shadowOpacity` iOS
+
+设置阴影不透明度(乘以颜色的 alpha 分量)。
+
+| 类型 |
+| ------ |
+| number |
+
+---
+
+### `shadowRadius` iOS
+
+设置阴影模糊半径。
+
+| 类型 |
+| ------ |
+| number |
diff --git a/cnwebsite/versioned_docs/version-0.85/share.md b/cnwebsite/versioned_docs/version-0.85/share.md
new file mode 100644
index 00000000000..bb85e8caa83
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/share.md
@@ -0,0 +1,136 @@
+---
+id: share
+title: Share
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+## 示例
+
+
+
+
+```SnackPlayer name=Example&supportedPlatforms=ios,android&ext=js
+import React from 'react';
+import {Alert, Share, Button} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+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) {
+ Alert.alert(error.message);
+ }
+ };
+ return (
+
+
+
+
+
+ );
+};
+
+export default ShareExample;
+```
+
+
+
+
+```SnackPlayer name=Example&supportedPlatforms=ios,android&ext=tsx
+import React from 'react';
+import {Alert, Share, Button} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+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;
+```
+
+
+
+
+# 参考文档
+
+## 方法
+
+### `share()`
+
+```tsx
+static share(content: ShareContent, options?: ShareOptions);
+```
+
+打开一个对话框来分享文本内容。
+
+在 iOS 中,返回一个 Promise,最终会解析为一个包含 `action` 和 `activityType` 的对象。如果用户关闭了对话框,Promise 仍然会被解析,此时 action 为 `Share.dismissedAction`,其他属性均为 undefined。请注意,某些分享选项在 iOS 模拟器上可能无法显示或正常工作。
+
+在 Android 中,返回一个 Promise,其 action 始终为 `Share.sharedAction`。
+
+**属性:**
+
+| 名称 | 类型 | 说明 |
+| -------------------------------------------------------- | ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| content 必需
| object | `message` - 要分享的消息 `url` - 要分享的网址 iOS
`title` - 消息的标题 Android
至少需要提供 `url` 或 `message` 中的一个。 |
+| options | object | `dialogTitle` Android
`excludedActivityTypes` iOS
`subject` - 通过邮件分享时的主题 iOS
`tintColor` iOS
`anchor` - 操作表应锚定到的节点(用于 iPad) iOS
|
+
+---
+
+## 属性
+
+### `sharedAction`
+
+```tsx
+static sharedAction: 'sharedAction';
+```
+
+表示内容已成功分享。
+
+---
+
+### `dismissedAction` iOS
+
+```tsx
+static dismissedAction: 'dismissedAction';
+```
+
+表示对话框已被关闭。
diff --git a/cnwebsite/versioned_docs/version-0.85/signed-apk-android.md b/cnwebsite/versioned_docs/version-0.85/signed-apk-android.md
new file mode 100644
index 00000000000..f88bc19fd8e
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/signed-apk-android.md
@@ -0,0 +1,196 @@
+---
+id: signed-apk-android
+title: 发布到 Google Play Store
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+Android 要求所有应用都有一个数字签名才会被允许安装在用户手机上。要通过 [Google Play 商店](https://play.google.com/store)发布你的 Android 应用,需要使用一个发布密钥对其进行签名,此后所有的更新也需要使用同一个密钥。自 2017 年起,借助 [Google Play 应用签名](https://developer.android.com/studio/publish/app-signing#app-signing-google-play)功能,Google Play 可以自动管理签名发布。但在将应用二进制文件上传到 Google Play 之前,仍需要使用上传密钥进行签名。Android 开发者官网上的[应用签名](https://developer.android.com/tools/publishing/app-signing.html)文档描述了签名的细节。本指南旨在提供一个简化的签名和打包流程,以及打包 JavaScript 代码所需的步骤。
+
+:::info
+如果你使用的是 Expo,请阅读 Expo 的[发布到应用商店](https://docs.expo.dev/distribution/app-stores/)指南来构建和提交应用到 Google Play 商店。此指南适用于任何 React Native 应用,可以自动化部署流程。
+:::
+
+## 生成上传密钥
+
+你可以用`keytool`命令生成一个私有签名密钥。
+
+### Windows
+
+在 Windows 上`keytool`命令需要在`C:\Program Files\Java\jdkx.x.x_x\bin`目录下以管理员身份运行。
+
+```shell
+keytool -genkeypair -v -storetype PKCS12 -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
+```
+
+这条命令会要求你输入密钥库(keystore)和对应密钥的密码,然后设置一些发行相关的信息。最后它会生成一个叫做`my-upload-key.keystore`的密钥库文件。
+
+在运行上面这条语句之后,密钥库里应该已经生成了一个单独的密钥,有效期为 10000 天。--alias 参数后面的别名是你将来为应用签名时所需要用到的,所以记得记录这个别名。
+
+### macOS
+
+在 macOS 上,如果你不确定 JDK bin 目录的位置,可以执行以下命令来查找:
+
+```shell
+/usr/libexec/java_home
+```
+
+它会输出 JDK 的目录,类似这样:
+
+```shell
+/Library/Java/JavaVirtualMachines/jdkX.X.X_XXX.jdk/Contents/Home
+```
+
+使用 `cd /your/jdk/path` 命令进入该目录,然后使用 sudo 权限执行 keytool 命令:
+
+```shell
+sudo keytool -genkey -v -keystore my-upload-key.keystore -alias my-key-alias -keyalg RSA -keysize 2048 -validity 10000
+```
+
+:::caution
+请记得妥善保管好你的密钥库文件,不要上传到版本库或其他公开的地方。如果你丢失了上传密钥或密钥被泄露,请[按照这些说明操作](https://support.google.com/googleplay/android-developer/answer/7384423#reset)。
+:::
+
+## 设置 Gradle 变量
+
+1. 把`my-upload-key.keystore`文件放到你工程中的`android/app`文件夹下。
+2. 编辑`~/.gradle/gradle.properties`(全局配置,对所有项目有效)或是`android/gradle.properties`(项目配置,只对所在项目有效),添加如下的代码(注意把其中的`*****`替换为相应密码):
+
+```
+MYAPP_UPLOAD_STORE_FILE=my-upload-key.keystore
+MYAPP_UPLOAD_KEY_ALIAS=my-key-alias
+MYAPP_UPLOAD_STORE_PASSWORD=*****
+MYAPP_UPLOAD_KEY_PASSWORD=*****
+```
+
+上面的这些会作为全局 Gradle 变量,在后面的步骤中可以用来给应用签名。
+
+:::note 关于使用 git 的说明
+将上述 Gradle 变量保存在 `~/.gradle/gradle.properties` 而非 `android/gradle.properties` 中,可以防止它们被提交到 git。你可能需要先在用户主目录下创建 `~/.gradle/gradle.properties` 文件。
+:::
+
+:::note 关于安全性的说明
+如果你不想以明文方式保存密码,且你使用的是 macOS 系统,你也可以把密码[保存到钥匙串(Keychain)中](https://pilloxa.gitlab.io/posts/safer-passwords-in-gradle/)。这样一来你就可以省略掉 `~/.gradle/gradle.properties` 中的后两行。
+:::
+
+## 在应用的 Gradle 配置中添加签名配置
+
+最后一步是配置 release 构建使用上传密钥进行签名。编辑你项目目录下的`android/app/build.gradle`,添加签名配置:
+
+```groovy
+...
+android {
+ ...
+ defaultConfig { ... }
+ signingConfigs {
+ release {
+ if (project.hasProperty('MYAPP_UPLOAD_STORE_FILE')) {
+ storeFile file(MYAPP_UPLOAD_STORE_FILE)
+ storePassword MYAPP_UPLOAD_STORE_PASSWORD
+ keyAlias MYAPP_UPLOAD_KEY_ALIAS
+ keyPassword MYAPP_UPLOAD_KEY_PASSWORD
+ }
+ }
+ }
+ buildTypes {
+ release {
+ ...
+ signingConfig signingConfigs.release
+ }
+ }
+}
+...
+```
+
+## 生成发行 AAB 包
+
+在终端中运行以下命令:
+
+```shell
+npx react-native build-android --mode=release
+```
+
+此命令底层使用 Gradle 的`bundleRelease`任务,会把所有用到的 JavaScript 代码都打包到 AAB([Android App Bundle](https://developer.android.com/guide/app-bundle))中。如果你需要调整 JavaScript 代码包和/或 drawable 资源的打包方式(比如修改了默认的文件/文件夹名称或项目的整体结构),请查看`android/app/build.gradle`来了解如何更新配置。
+
+:::note
+请确保 gradle.properties 中**没有**包含`org.gradle.configureondemand=true`,否则会跳过 JS 打包的步骤,导致最终生成的是一个无法运行的空壳。
+:::
+
+生成的 AAB 文件位于`android/app/build/outputs/bundle/release/app-release.aab`,可以直接上传到 Google Play。
+
+要让 Google Play 接受 AAB 格式,需要在 Google Play Console 中为应用配置 Google Play 应用签名。如果你正在更新一个尚未使用 Google Play 应用签名的现有应用,请查看[迁移指南](#迁移旧版-android-react-native-应用到-google-play-应用签名)了解如何进行配置更改。
+
+## 测试应用的发行版本
+
+在将发行版本上传到 Play Store 之前,请确保彻底测试。首先卸载已安装的所有该应用的旧版本,然后在项目根目录下使用以下命令安装到设备:
+
+
+
+
+```shell
+npm run android -- --mode="release"
+```
+
+
+
+
+```shell
+yarn android --mode release
+```
+
+
+
+
+注意`--mode release`参数只能在你完成了上面的签名配置之后才可以使用。
+
+你现在可以关掉运行中的 bundler 了,因为你所有的框架和 JavaScript 代码已经都被打包到 APK 的 assets 中了。
+
+## 发布到其他商店
+
+默认情况下,生成的 APK 会同时包含 `x86`、`x86_64`、`ARMv7a` 和 `ARM64-v8a` CPU 架构的原生代码。这使得分享可以在几乎所有 Android 设备上运行的 APK 更加方便。但是,这意味着在任何设备上都会有一些未使用的原生代码,导致 APK 不必要地变大。
+
+你可以在`android/app/build.gradle`中添加如下代码来为每种 CPU 架构生成单独的 APK:
+
+```diff
+android {
+
+ splits {
+ abi {
+ reset()
+ enable true
+ universalApk false
+ include "armeabi-v7a", "arm64-v8a", "x86", "x86_64"
+ }
+ }
+
+}
+```
+
+你可以把这些文件上传到支持设备定位的商店,如 [Amazon AppStore](https://developer.amazon.com/docs/app-submission/device-filtering-and-compatibility.html) 或 [F-Droid](https://f-droid.org/en/),用户将自动获得适当的 APK。如果你想上传到其他不支持单个应用多个 APK 的商店(如 [APKFiles](https://www.apkfiles.com/)),请将 `universalApk false` 改为 `true`,以生成包含所有 CPU 架构的通用 APK。
+
+请注意,你还需要配置不同的版本代码,如官方 Android 文档[此页面](https://developer.android.com/studio/build/configure-apk-splits#configure-APK-versions)所建议的。
+
+## 启用 Proguard 来减少 APK 的大小(可选)
+
+Proguard 是一个 Java 字节码混淆压缩工具,它可以移除掉 React Native Java(和它的依赖库中)未被使用到的部分,从而有效地减少 APK 的大小。
+
+:::caution 重要
+启用 Proguard 之后,你必须再次全面地测试你的应用。Proguard 有时候需要为你引入的每个原生库做一些额外的配置。参见`app/proguard-rules.pro`文件。
+:::
+
+要启用 Proguard,修改`android/app/build.gradle`文件:
+
+```groovy
+/**
+ * Run Proguard to shrink the Java bytecode in release builds.
+ */
+def enableProguardInReleaseBuilds = true
+```
+
+## 迁移旧版 Android React Native 应用到 Google Play 应用签名
+
+如果你是从旧版 React Native 迁移过来的,你的应用很可能还没有使用 Google Play 应用签名功能。我们建议你启用该功能以利用自动应用拆分等优势。要从旧的签名方式迁移,你需要先[生成新的上传密钥](#生成上传密钥),然后将 `android/app/build.gradle` 中的发布签名配置替换为使用上传密钥(参见[添加签名配置到 Gradle](#在应用的-gradle-配置中添加签名配置))。完成后,请按照 [Google Play 帮助网站的说明](https://support.google.com/googleplay/android-developer/answer/7384423)将你的原始发布密钥发送给 Google Play。
+
+## 默认权限
+
+默认情况下,`INTERNET` 权限会被添加到你的 Android 应用中,因为几乎所有应用都需要使用它。`SYSTEM_ALERT_WINDOW` 权限在 debug 模式下会添加到 APK 中,但在 production 构建中会被移除。
diff --git a/cnwebsite/versioned_docs/version-0.85/state.md b/cnwebsite/versioned_docs/version-0.85/state.md
new file mode 100644
index 00000000000..b3b91a86330
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/state.md
@@ -0,0 +1,103 @@
+---
+id: state
+title: State(状态)
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+我们使用两种数据来控制一个组件:`props`和`state`。`props`是在父组件中指定,而且一经指定,在被指定的组件的生命周期中则不再改变。对于需要改变的数据,我们需要使用`state`。
+
+一般来说,你需要在构造函数中初始化`state`,然后在需要修改时调用`setState`。
+
+假如我们需要制作一段不停闪烁的文字。文字内容本身在组件创建时就已经指定好了,所以文字内容应该是一个`prop`。而文字的显示或隐藏的状态(快速的显隐切换就产生了闪烁的效果)则是随着时间变化的,因此这一状态应该写到`state`中。
+
+
+
+
+```SnackPlayer name=State&ext=js
+import React, {useState, useEffect} from 'react';
+import {Text, View} from 'react-native';
+
+const Blink = props => {
+ 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;
+```
+
+
+
+
+```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;
+```
+
+
+
+
+实际开发中,我们一般不会在定时器函数(setInterval、setTimeout 等)中来操作 state。典型的场景是在接收到服务器返回的新数据,或者在用户输入数据之后。你也可以使用一些"状态容器"比如[Redux](https://redux.js.org/)或[MobX](https://mobx.js.org/)来统一管理数据流。在这种情况下,你可以使用 Redux 或 MobX 来修改 state,而不是直接调用`setState`。
+
+每次调用`setState`时,BlinkApp 都会重新执行 render 方法重新渲染。这里我们使用定时器来不停调用`setState`,于是组件就会随着时间变化不停地重新渲染。
+
+State 的工作原理和 React 完全一致,所以对于处理 state 的一些更深入的细节,你可以参阅[React.Component API](https://react.dev/reference/react/Component#setstate)。看到这里,你可能觉得我们的例子总是千篇一律的黑色文本,那么我们一起来[学习一下样式](style.md)吧。
diff --git a/cnwebsite/versioned_docs/version-0.85/statusbar.md b/cnwebsite/versioned_docs/version-0.85/statusbar.md
new file mode 100644
index 00000000000..0fcb04f1490
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/statusbar.md
@@ -0,0 +1,513 @@
+---
+id: statusbar
+title: StatusBar
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+用于控制应用状态栏的组件。状态栏是屏幕顶部的区域,通常显示当前时间、Wi-Fi 和蜂窝网络信息、电池电量和/或其他状态图标。
+
+### 和导航器一起使用
+
+可以同时挂载多个 `StatusBar` 组件。属性将按照 `StatusBar` 组件的挂载顺序进行合并。
+
+
+
+
+```SnackPlayer name=StatusBar%20Component%20Example&supportedPlatforms=android,ios&ext=js
+import React, {useState} from 'react';
+import {
+ Button,
+ Platform,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const STYLES = ['default', 'dark-content', 'light-content'];
+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 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;
+```
+
+
+
+
+```SnackPlayer name=StatusBar%20Component%20Example&supportedPlatforms=android,ios&ext=tsx
+import React, {useState} from 'react';
+import {
+ Button,
+ Platform,
+ StatusBar,
+ StyleSheet,
+ Text,
+ View,
+ StatusBarStyle,
+} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+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;
+```
+
+
+
+
+### 命令式 API
+
+对于不适合使用组件的场景,StatusBar 也提供了以组件静态方法形式暴露的命令式 API。不过不推荐同时使用静态 API 和组件来设置同一个属性,因为静态 API 设置的值会在下一次渲染时被组件设置的值覆盖。
+
+---
+
+# 参考
+
+## 常量
+
+### `currentHeight` Android
+
+状态栏的高度,包括刘海高度(如果有的话)。
+
+---
+
+## Props
+
+### `animated`
+
+状态栏属性变化时是否使用动画过渡。支持 `backgroundColor`、`barStyle` 和 `hidden` 属性。
+
+| 类型 | 必需 | 默认值 |
+| ------- | ---- | ------- |
+| boolean | 否 | `false` |
+
+---
+
+### `backgroundColor` Android
+
+状态栏的背景色。
+
+:::warning
+由于 Android 15 引入的全面屏(edge-to-edge)强制要求,在 API level 35 中设置状态栏背景色已被弃用,设置将不会生效。你可以在[这里阅读我们的全面屏适配建议](https://github.com/react-native-community/discussions-and-proposals/discussions/827)。
+:::
+
+| 类型 | 必需 | 默认值 |
+| --------------- | ---- | ---------------------------------------------- |
+| [color](colors) | 否 | 默认系统状态栏背景色,如果未定义则为 `'black'` |
+
+---
+
+### `barStyle`
+
+设置状态栏文本的颜色。
+
+在 Android 上,此属性仅对 API 23 及以上版本生效。
+
+| 类型 | 必需 | 默认值 |
+| ------------------------------------------ | ---- | ----------- |
+| [StatusBarStyle](statusbar#statusbarstyle) | 否 | `'default'` |
+
+---
+
+### `hidden`
+
+是否隐藏状态栏。
+
+| 类型 | 必需 | 默认值 |
+| ------- | ---- | ------- |
+| boolean | 否 | `false` |
+
+---
+
+### `networkActivityIndicatorVisible` iOS
+
+是否显示网络活动指示器。
+
+| 类型 | 默认值 |
+| ------- | ------- |
+| boolean | `false` |
+
+---
+
+### `showHideTransition` iOS
+
+使用 `hidden` 属性显示和隐藏状态栏时的过渡效果。
+
+| 类型 | 默认值 |
+| -------------------------------------------------- | -------- |
+| [StatusBarAnimation](statusbar#statusbaranimation) | `'fade'` |
+
+---
+
+### `translucent` Android
+
+指定状态栏是否透明。设置为 `true` 时,应用会在状态栏下方绘制内容。这在使用半透明状态栏背景色时非常有用。
+
+:::warning
+由于 Android 15 引入的全面屏(edge-to-edge)强制要求,在 API level 35 中设置状态栏透明已被弃用,设置将不会生效。你可以在[这里阅读我们的全面屏适配建议](https://github.com/react-native-community/discussions-and-proposals/discussions/827)。
+:::
+
+| 类型 | 默认值 |
+| ------- | ------- |
+| boolean | `false` |
+
+## 方法
+
+### `popStackEntry()`
+
+```tsx
+static popStackEntry(entry: StatusBarProps);
+```
+
+获取并移除栈中最后一个 StatusBar 条目。
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------ | ---- | ----------------------------- |
+| entry 必需
| any | `pushStackEntry` 返回的条目。 |
+
+---
+
+### `pushStackEntry()`
+
+```tsx
+static pushStackEntry(props: StatusBarProps): StatusBarProps;
+```
+
+将一个 StatusBar 条目压入栈中。返回值应在完成后传递给 `popStackEntry`。
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------ | ---- | --------------------------------------------- |
+| props 必需
| any | 包含要在栈条目中使用的 StatusBar 属性的对象。 |
+
+---
+
+### `replaceStackEntry()`
+
+```tsx
+static replaceStackEntry(
+ entry: StatusBarProps,
+ props: StatusBarProps
+): StatusBarProps;
+```
+
+用新的属性替换栈中已有的 StatusBar 条目。
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------ | ---- | ------------------------------------------------- |
+| entry 必需
| any | 要替换的 `pushStackEntry` 返回的条目。 |
+| props 必需
| any | 包含要在替换栈条目中使用的 StatusBar 属性的对象。 |
+
+---
+
+### `setBackgroundColor()` Android
+
+```tsx
+static setBackgroundColor(color: ColorValue, animated?: boolean);
+```
+
+设置状态栏的背景色。
+
+:::warning
+由于 Android 15 引入的全面屏(edge-to-edge)强制要求,在 API level 35 中设置状态栏背景色已被弃用,设置将不会生效。你可以在[这里阅读我们的全面屏适配建议](https://github.com/react-native-community/discussions-and-proposals/discussions/827)。
+:::
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------ | ------- | ------------------ |
+| color 必需
| string | 背景色。 |
+| animated | boolean | 是否使用动画过渡。 |
+
+---
+
+### `setBarStyle()`
+
+```tsx
+static setBarStyle(style: StatusBarStyle, animated?: boolean);
+```
+
+设置状态栏的样式。
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------ | ------------------------------------------ | -------------------- |
+| style 必需
| [StatusBarStyle](statusbar#statusbarstyle) | 要设置的状态栏样式。 |
+| animated | boolean | 是否使用动画过渡。 |
+
+---
+
+### `setHidden()`
+
+```tsx
+static setHidden(hidden: boolean, animation?: StatusBarAnimation);
+```
+
+显示或隐藏状态栏。
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------- | -------------------------------------------------- | -------------------------------- |
+| hidden 必需
| boolean | 是否隐藏状态栏。 |
+| animation iOS
| [StatusBarAnimation](statusbar#statusbaranimation) | 改变状态栏隐藏属性时的动画效果。 |
+
+---
+
+### 🗑️ `setNetworkActivityIndicatorVisible()` iOS
+
+:::warning 已弃用
+iOS 13 及更高版本不再支持状态栏网络活动指示器。此方法将在未来版本中移除。
+:::
+
+```tsx
+static setNetworkActivityIndicatorVisible(visible: boolean);
+```
+
+控制网络活动指示器的可见性。
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| -------------------------------------------------------- | ------- | ---------------- |
+| visible 必需
| boolean | 是否显示指示器。 |
+
+---
+
+### `setTranslucent()` Android
+
+```tsx
+static setTranslucent(translucent: boolean);
+```
+
+控制状态栏的透明度。
+
+:::warning
+由于 Android 15 引入的全面屏(edge-to-edge)强制要求,在 API level 35 中设置状态栏透明已被弃用,设置将不会生效。你可以在[这里阅读我们的全面屏适配建议](https://github.com/react-native-community/discussions-and-proposals/discussions/827)。
+:::
+
+**参数:**
+
+| 名称 | 类型 | 描述 |
+| ------------------------------------------------------------ | ------- | ------------ |
+| translucent 必需
| boolean | 设置为透明。 |
+
+## 类型定义
+
+### StatusBarAnimation
+
+iOS 上状态栏的过渡动画类型。
+
+| 类型 |
+| ---- |
+| enum |
+
+**常量:**
+
+| 值 | 类型 | 描述 |
+| --------- | ------ | -------- |
+| `'fade'` | string | 渐变动画 |
+| `'slide'` | string | 滑动动画 |
+| `'none'` | string | 无动画 |
+
+---
+
+### StatusBarStyle
+
+状态栏样式类型。
+
+| 类型 |
+| ---- |
+| enum |
+
+**常量:**
+
+| 值 | 类型 | 描述 |
+| ----------------- | ------ | -------------------------------------------- |
+| `'default'` | string | 默认状态栏样式(iOS 为深色,Android 为浅色) |
+| `'light-content'` | string | 白色文字和图标 |
+| `'dark-content'` | string | 深色文字和图标(Android 上需要 API>=23) |
diff --git a/cnwebsite/versioned_docs/version-0.85/statusbarios.md b/cnwebsite/versioned_docs/version-0.85/statusbarios.md
new file mode 100644
index 00000000000..ddea232d3ee
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/statusbarios.md
@@ -0,0 +1,10 @@
+---
+id: statusbarios
+title: '❌ StatusBarIOS'
+---
+
+:::danger 已从 React Native 中移除
+请使用 [`StatusBar`](statusbar.md) 来操作状态栏。
+:::
+
+---
diff --git a/cnwebsite/versioned_docs/version-0.85/strict-typescript-api.md b/cnwebsite/versioned_docs/version-0.85/strict-typescript-api.md
new file mode 100644
index 00000000000..20a541b82d1
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/strict-typescript-api.md
@@ -0,0 +1,191 @@
+---
+id: strict-typescript-api
+title: 严格 TypeScript API(可选加入)
+---
+
+严格 TypeScript API 是我们未来稳定的 React Native JavaScript API 的预览版。
+
+具体来说,这是 `react-native` npm 包的一套新的 TypeScript 类型,从 0.80 版本开始提供。这些类型提供了更强大、更面向未来的类型准确性,并将允许我们自信地将 React Native 的 API 演进为稳定的形状。选择加入严格 TypeScript API 会带来一些结构性类型差异,因此这是一次性的破坏性更改。
+
+新类型具有以下特点:
+
+1. **直接从我们的源代码生成** — 提高覆盖率和正确性,因此你可以期待更强的兼容性保证。
+2. **限制在 `react-native` 的索引文件中** — 更严格地定义我们的公共 API,意味着我们在进行内部文件更改时不会破坏 API。
+
+当社区准备好时,严格 TypeScript API 将在未来成为我们的默认 API — 与深度导入移除同步。
+
+## 选择加入
+
+我们将这些新类型与现有类型一起发布,这意味着你可以在准备好时选择迁移。我们鼓励早期采用者和新创建的应用通过 `tsconfig.json` 文件选择加入。
+
+选择加入是一个**破坏性更改**,因为我们的一些新类型具有更新的名称和结构,尽管许多应用不会受到影响。你可以在下一节中了解每个破坏性更改。
+
+```json title="tsconfig.json"
+{
+ "extends": "@react-native/typescript-config",
+ "compilerOptions": {
+ ...
+ "customConditions": ["react-native-strict-api"]
+ }
+}
+```
+
+:::note 底层原理
+
+这将指示 TypeScript 从我们新的 [`types_generated/`](https://www.npmjs.com/package/react-native?activeTab=code) 目录解析 `react-native` 类型,而不是之前的 [`types/`](https://www.npmjs.com/package/react-native?activeTab=code) 目录(手动维护)。不需要重启 TypeScript 或你的编辑器。
+
+:::
+
+严格 TypeScript API 遵循我们的 [RFC](https://github.com/react-native-community/discussions-and-proposals/pull/894) 来移除 React Native 中的深度导入。因此,一些 API 不再在根目录中导出。这是有意的,目的是减少 React Native API 的整体表面积。
+
+:::tip API 反馈
+
+**发送反馈**:我们将与社区合作,在(至少)接下来的两个 React Native 版本中确定我们导出哪些 API。请在我们的[反馈线程](https://github.com/react-native-community/discussions-and-proposals/discussions/893)中分享你的反馈。
+
+参见我们的[公告博客文章](/blog/2025/06/12/moving-towards-a-stable-javascript-api),了解更多关于我们动机和时间表的信息。
+
+:::
+
+## 迁移指南
+
+### Codegen 类型现在应从 `react-native` 包中导入
+
+用于 codegen 的类型,如 `Int32`、`Double`、`WithDefault` 等,现在在单个 `CodegenTypes` 命名空间下可用。同样,`codegenNativeComponent` 和 `codegenNativeCommands` 现在可以从 react-native 包中导入,而不需要使用深度导入。
+
+当未启用严格 API 时,命名空间 `CodegenTypes` 以及 `codegenNativeCommands` 和 `codegenNativeComponent` 也可以从 `react-native` 包中获取,以便第三方库更容易采用。
+
+**之前**
+
+```ts title=""
+import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
+import type {
+ Int32,
+ WithDefault,
+} from 'react-native/Libraries/Types/CodegenTypes';
+
+interface NativeProps extends ViewProps {
+ enabled?: WithDefault;
+ size?: Int32;
+}
+
+export default codegenNativeComponent(
+ 'RNCustomComponent',
+);
+```
+
+**之后**
+
+```ts title=""
+import {CodegenTypes, codegenNativeComponent} from 'react-native';
+
+interface NativeProps extends ViewProps {
+ enabled?: CodegenTypes.WithDefault;
+ size?: CodegenTypes.Int32;
+}
+
+export default codegenNativeComponent(
+ 'RNCustomComponent',
+);
+```
+
+### 移除 `*Static` 类型
+
+**之前**
+
+```tsx title=""
+import {Linking, LinkingStatic} from 'react-native';
+
+function foo(linking: LinkingStatic) {}
+foo(Linking);
+```
+
+**之后**
+
+```tsx title=""
+import {Linking} from 'react-native';
+
+function foo(linking: Linking) {}
+foo(Linking);
+```
+
+以下 API 之前被命名为 `*Static` 加上该类型的变量声明。在大多数情况下,有一个别名,使得值和类型在相同的标识符下导出,但有些是缺失的。
+
+(例如,有一个 `AlertStatic` 类型、类型为 `AlertStatic` 的 `Alert` 变量和作为 `AlertStatic` 别名的 `Alert` 类型。但在 `PixelRatio` 的情况下,有一个 `PixelRatioStatic` 类型和该类型的 `PixelRatio` 变量,但没有额外的类型别名。)
+
+**受影响的 API**
+
+- `AlertStatic`
+- `ActionSheetIOSStatic`
+- `ToastAndroidStatic`
+- `InteractionManagerStatic` (In this case there was no relevant `InteractionManager` type alias)
+- `UIManagerStatic`
+- `PlatformStatic`
+- `SectionListStatic`
+- `PixelRatioStatic` (In this case there was no relevant `PixelRatio` type alias)
+- `AppStateStatic`
+- `AccessibilityInfoStatic`
+- `ImageResizeModeStatic`
+- `BackHandlerStatic`
+- `DevMenuStatic` (In this case there was no relevant `DevMenu` type alias)
+- `ClipboardStatic`
+- `PermissionsAndroidStatic`
+- `ShareStatic`
+- `DeviceEventEmitterStatic`
+- `LayoutAnimationStatic`
+- `KeyboardStatic` (In this case there was no relevant `Keyboard` type alias)
+- `DevSettingsStatic` (In this case there was no relevant `DevSettings` type alias)
+- `I18nManagerStatic`
+- `EasingStatic`
+- `PanResponderStatic`
+- `NativeModulesStatic` (In this case there was no relevant `NativeModules` type alias)
+- `LogBoxStatic`
+- `PushNotificationIOSStatic`
+- `SettingsStatic`
+- `VibrationStatic`
+
+### 一些核心组件现在是函数组件而不是类组件
+
+- `View`
+- `Image`
+- `TextInput`
+- `Modal`
+- `Text`
+- `TouchableWithoutFeedback`
+- `Switch`
+- `ActivityIndicator`
+- `ProgressBarAndroid`
+- `InputAccessoryView`
+- `Button`
+- `SafeAreaView`
+
+由于这个变化,访问这些视图的 ref 类型需要使用 `React.ComponentRef` 模式,这对类组件和函数组件都按预期工作,例如:
+
+```ts title=""
+const ref = useRef>(null);
+```
+
+## 其他破坏性更改
+
+### Animated 类型的变化
+
+Animated 节点之前是基于其插值输出的泛型类型。现在,它们是具有泛型 `interpolate` 方法的非泛型类型。
+
+`Animated.LegacyRef` 不再可用。
+
+### 可选属性的统一类型
+
+在新类型中,每个可选属性都将被类型化为 `type | undefined`。
+
+### 移除一些已废弃的类型
+
+[`DeprecatedPropertiesAlias.d.ts`](https://github.com/facebook/react-native/blob/0.80-stable/packages/react-native/types/public/DeprecatedPropertiesAlias.d.ts) 中列出的所有类型在严格 API 下都无法访问。
+
+### 移除剩余的组件属性
+
+一些在类型定义中定义但组件未使用或缺少定义的属性被移除了(例如:`Text` 上的 `lineBreakMode`、`ScrollView` 上的 `scrollWithoutAnimationTo`、在 transform 数组外定义的 transform 样式)。
+
+### 之前可访问的私有类型帮助器现在可能被移除
+
+由于之前类型定义的配置,每个定义的类型都可以从 `react-native` 包中访问。这包括没有显式导出的类型和仅供内部使用的帮助类型。
+
+这方面的显著例子是与 StyleSheet 相关的类型(如 `RecursiveArray`、`RegisteredStyle` 和 `Falsy`)和 Animated 相关的类型(如 `WithAnimatedArray` 和 `WithAnimatedObject`)。
diff --git a/cnwebsite/versioned_docs/version-0.85/style.md b/cnwebsite/versioned_docs/version-0.85/style.md
new file mode 100644
index 00000000000..a60b9e85650
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/style.md
@@ -0,0 +1,52 @@
+---
+id: style
+title: 样式
+---
+
+在 React Native 中,你并不需要学习什么特殊的语法来定义样式。我们仍然是使用 JavaScript 来写样式。所有的核心组件都接受名为`style`的属性。这些样式名基本上是遵循了 web 上的 CSS 的命名,只是按照 JS 的语法要求使用了驼峰命名法,例如将`background-color`改为`backgroundColor`。
+
+`style`属性可以是一个普通的 JavaScript 对象。这是最简单的用法,因而在示例代码中很常见。你还可以传入一个数组——在数组中位置居后的样式对象比居前的优先级更高,这样你可以间接实现样式的继承。
+
+实际开发中组件的样式会越来越复杂,我们建议使用`StyleSheet.create`来集中定义组件的样式。比如像下面这样:
+
+```SnackPlayer name=Style
+import React from 'react';
+import { StyleSheet, Text, View } from 'react-native';
+
+const LotsOfStyles = () => {
+ return (
+
+ just red
+ just bigBlue
+ bigBlue, then red
+ red, then bigBlue
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ marginTop: 50,
+ },
+ bigBlue: {
+ color: 'blue',
+ fontWeight: 'bold',
+ fontSize: 30,
+ },
+ red: {
+ color: 'red',
+ },
+});
+
+export default LotsOfStyles;
+```
+
+常见的做法是按顺序声明和使用`style`属性,以借鉴 CSS 中的“层叠”做法(即后声明的属性会覆盖先声明的同名属性)。
+
+文本的样式定义请参阅[Text 组件的文档](text.md)。
+
+现在你已经了解如何调整文本样式了,下面我们要学习的是[如何控制组件的尺寸](height-and-width.md)。
+
+## 已知问题
+
+- [react-native#29308](https://github.com/facebook/react-native/issues/29308#issuecomment-792864162):在某些情况下,React Native 与 web 上 CSS 的工作方式不一致,例如触摸区域永远不会超出父视图的边界,以及在 Android 上不支持负 margin。
diff --git a/cnwebsite/versioned_docs/version-0.85/stylesheet.md b/cnwebsite/versioned_docs/version-0.85/stylesheet.md
new file mode 100644
index 00000000000..9503111aa2c
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/stylesheet.md
@@ -0,0 +1,351 @@
+---
+id: stylesheet
+title: StyleSheet
+---
+
+StyleSheet 是一个类似于 CSS StyleSheets 的抽象层。
+
+```SnackPlayer name=StyleSheet
+import React from 'react';
+import {StyleSheet, Text} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => (
+
+
+ React Native
+
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 24,
+ backgroundColor: '#eaeaea',
+ },
+ title: {
+ marginTop: 16,
+ paddingVertical: 8,
+ borderWidth: 4,
+ borderColor: '#20232a',
+ borderRadius: 6,
+ backgroundColor: '#61dafb',
+ color: '#20232a',
+ textAlign: 'center',
+ fontSize: 30,
+ fontWeight: 'bold',
+ },
+});
+
+export default App;
+```
+
+代码质量建议:
+
+- 将样式从渲染函数中分离出来,可以使代码更容易理解。
+- 为样式命名是为渲染函数中的低级组件赋予语义的好方法,也有助于样式复用。
+- 在大多数 IDE 中,使用 `StyleSheet.create()` 可以提供静态类型检查和建议,帮助你编写合法的样式。
+
+---
+
+# 参考文档
+
+## 方法
+
+### `compose()`
+
+```tsx
+static compose(style1: Object, style2: Object): Object | Object[];
+```
+
+将两个样式组合在一起,使得 `style2` 会覆盖 `style1` 中的任何样式。如果其中任何一个样式为 falsy,则直接返回另一个,不会分配数组,从而节省内存分配并保持 PureComponent 检查的引用相等性。
+
+```SnackPlayer name=Compose
+import React from 'react';
+import {StyleSheet, Text} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => (
+
+
+ React Native
+
+
+);
+
+const page = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 24,
+ backgroundColor: '#fff',
+ },
+ text: {
+ fontSize: 30,
+ color: '#000',
+ },
+});
+
+const lists = StyleSheet.create({
+ listContainer: {
+ flex: 1,
+ backgroundColor: '#61dafb',
+ },
+ listItem: {
+ fontWeight: 'bold',
+ },
+});
+
+const container = StyleSheet.compose(page.container, lists.listContainer);
+const text = StyleSheet.compose(page.text, lists.listItem);
+
+export default App;
+```
+
+---
+
+### `create()`
+
+```tsx
+static create(styles: Object extends Record): Object;
+```
+
+一个用于创建样式的恒等函数。在 `StyleSheet.create()` 中创建样式的主要实际好处是可以对原生样式属性进行静态类型检查。
+
+---
+
+### `flatten()`
+
+```tsx
+static flatten(style: Array>): Object;
+```
+
+将样式对象数组扁平化为一个聚合的样式对象。
+
+```SnackPlayer name=Flatten
+import React from 'react';
+import {StyleSheet, Text} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => (
+
+
+ React Native
+ Flatten Style
+ {JSON.stringify(flattenStyle, null, 2)}
+
+
+);
+
+const page = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 24,
+ alignItems: 'center',
+ },
+ text: {
+ color: '#000',
+ fontSize: 14,
+ fontWeight: 'bold',
+ },
+ code: {
+ marginTop: 12,
+ padding: 12,
+ borderRadius: 8,
+ color: '#666',
+ backgroundColor: '#eaeaea',
+ },
+});
+
+const typography = StyleSheet.create({
+ header: {
+ color: '#61dafb',
+ fontSize: 30,
+ marginBottom: 36,
+ },
+});
+
+const flattenStyle = StyleSheet.flatten([page.text, typography.header]);
+
+export default App;
+```
+
+---
+
+### `setStyleAttributePreprocessor()`
+
+:::warning 实验性功能
+可能会频繁发生破坏性变更,且不一定会提前通知。整个功能都可能被删除。使用需自担风险。
+:::
+
+```tsx
+static setStyleAttributePreprocessor(
+ property: string,
+ process: (propValue: any) => any,
+);
+```
+
+设置一个用于预处理样式属性值的函数。此方法在内部用于处理颜色和变换值。除非你确实清楚自己在做什么并且已经穷尽了其他方案,否则不应使用此方法。
+
+## 属性
+
+---
+
+### `absoluteFill`
+
+一种非常常见的模式是使用 `position: 'absolute'` 和零定位(`position: 'absolute', left: 0, right: 0, top: 0, bottom: 0`)来创建覆盖层,因此可以使用 `absoluteFill` 来简化代码并减少这些重复样式。如果需要,absoluteFill 可用于在 StyleSheet 中创建自定义条目,例如:
+
+```SnackPlayer name=absoluteFill
+import React from 'react';
+import {StyleSheet, Text, View} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => (
+
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ box1: {
+ position: 'absolute',
+ top: 40,
+ left: 40,
+ width: 100,
+ height: 100,
+ backgroundColor: 'red',
+ },
+ box2: {
+ width: 100,
+ height: 100,
+ backgroundColor: 'blue',
+ },
+ box3: {
+ position: 'absolute',
+ top: 120,
+ left: 120,
+ width: 100,
+ height: 100,
+ backgroundColor: 'green',
+ },
+ text: {
+ color: '#FFF',
+ fontSize: 80,
+ },
+});
+
+export default App;
+```
+
+---
+
+### `absoluteFillObject`
+
+有时你可能想要 `absoluteFill` 但需要做一些微调——`absoluteFillObject` 可用于在 `StyleSheet` 中创建自定义条目,例如:
+
+```SnackPlayer name=absoluteFillObject
+import React from 'react';
+import {StyleSheet, Text, View} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => (
+
+
+
+ 1
+
+
+ 2
+
+
+ 3
+
+
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ box1: {
+ position: 'absolute',
+ top: 40,
+ left: 40,
+ width: 100,
+ height: 100,
+ backgroundColor: 'red',
+ },
+ box2: {
+ ...StyleSheet.absoluteFillObject,
+ top: 120,
+ left: 50,
+ width: 100,
+ height: 100,
+ backgroundColor: 'blue',
+ },
+ box3: {
+ ...StyleSheet.absoluteFillObject,
+ top: 120,
+ left: 120,
+ width: 100,
+ height: 100,
+ backgroundColor: 'green',
+ },
+ text: {
+ color: '#FFF',
+ fontSize: 80,
+ },
+});
+
+export default App;
+```
+
+---
+
+### `hairlineWidth`
+
+定义为平台上细线的宽度。可以用作边框或两个元素之间分隔线的粗细。示例:
+
+```SnackPlayer name=hairlineWidth
+import React from 'react';
+import {StyleSheet, Text, View} from 'react-native';
+
+const App = () => (
+
+ React
+ Native
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ padding: 24,
+ },
+ row: {
+ padding: 4,
+ borderBottomColor: 'red',
+ borderBottomWidth: StyleSheet.hairlineWidth,
+ },
+});
+
+export default App;
+```
+
+此常量始终是整数像素值(因此由它定义的线条看起来会很清晰),并且会尽量匹配底层平台上细线的标准宽度。但你不应依赖它是一个固定大小,因为在不同平台和屏幕密度下,其值可能会以不同方式计算。
+
+如果模拟器被缩小显示,hairline width 的线条可能不可见。
diff --git a/cnwebsite/versioned_docs/version-0.85/switch.md b/cnwebsite/versioned_docs/version-0.85/switch.md
new file mode 100644
index 00000000000..b20166cc2e5
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/switch.md
@@ -0,0 +1,133 @@
+---
+id: switch
+title: Switch
+---
+
+跨平台通用的“开关”组件。
+
+注意这是一个“受控组件”(controlled component)。你必须使用`onValueChange`回调来更新`value`属性以响应用户的操作。如果不更新`value`属性,组件只会按一开始给定的`value`值来渲染且保持不变,看上去就像完全点不动。
+
+## 示例
+
+```SnackPlayer name=Switch&supportedPlatforms=android,ios
+import React, {useState} from 'react';
+import {Switch, StyleSheet} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ const [isEnabled, setIsEnabled] = useState(false);
+ const toggleSwitch = () => setIsEnabled(previousState => !previousState);
+
+ return (
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+});
+
+export default App;
+```
+
+---
+
+# 文档
+
+## Props
+
+### [View Props](view.md#props)
+
+继承了所有的[View Props](view.md#props).
+
+---
+
+### `disabled`
+
+如果为`true`则禁用此组件的交互。
+
+| 类型 | Default |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `ios_backgroundColor` iOS
+
+在 iOS 上,自定义背景颜色。这种背景颜色可以在开关值为`false`时或开关被禁用(且开关呈半透明状态)时看到。
+
+| 类型 |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `onChange`
+
+当值改变的时候调用此回调函数,参数为事件。如果你只想接收新值,请改用 `onValueChange`。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `onValueChange`
+
+当值改变的时候调用此回调函数,参数为新的值。如果你想接收一个完整事件,请使用 `onChange`。
+
+| 类型 |
+| -------- |
+| function |
+
+---
+
+### `ref`
+
+一个 ref 设置器,在组件挂载时会被分配一个[元素节点](element-nodes)。
+
+---
+
+### `thumbColor`
+
+开关上圆形按钮的背景颜色。在 iOS 上设置此颜色会丢失按钮的投影效果。
+
+| 类型 |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `trackColor`
+
+关闭状态时的边框颜色(iOS)或背景颜色(Android)。
+
+_iOS_: 当开关值为 `false` 时,轨道会收缩到边框内。如果你想改变收缩后轨道露出的背景颜色,请使用 [`ios_backgroundColor`](switch.md#ios_backgroundColor)。
+
+| Type |
+| ------------------------------------------------------------ |
+| `md object: {false: [color](colors), true: [color](colors)}` |
+
+---
+
+### `value`
+
+表示此开关是否打开。默认为 false(关闭状态)。
+
+| 类型 |
+| ---- |
+| bool |
diff --git a/cnwebsite/versioned_docs/version-0.85/systrace.md b/cnwebsite/versioned_docs/version-0.85/systrace.md
new file mode 100644
index 00000000000..f100201fc25
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/systrace.md
@@ -0,0 +1,139 @@
+---
+id: systrace
+title: Systrace
+---
+
+`Systrace` 是一个标准的基于标记的 Android 性能分析工具(在安装 Android platform-tools 包时会一起安装)。被分析的代码块会被开始/结束标记包围,然后以彩色图表格式可视化。Android SDK 和 React Native 框架都提供了可以可视化的标准标记。
+
+## 示例
+
+`Systrace` 允许您使用标签和整数值标记 JavaScript (JS) 事件。在 EasyProfiler 中捕获非计时的 JS 事件。
+
+```SnackPlayer name=Systrace%20Example
+import React from 'react';
+import {Button, Text, View, StyleSheet, Systrace} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ const enableProfiling = () => {
+ Systrace.setEnabled(true); // 调用 setEnabled 来开启性能分析
+ Systrace.beginEvent('event_label');
+ Systrace.counterEvent('event_label', 10);
+ };
+
+ const stopProfiling = () => {
+ Systrace.endEvent();
+ };
+
+ return (
+
+
+
+ React Native Systrace API
+
+
+ enableProfiling()}
+ />
+ stopProfiling()}
+ color="#FF0000"
+ />
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#fff',
+ alignItems: 'center',
+ justifyContent: 'center',
+ padding: 8,
+ gap: 16,
+ },
+ header: {
+ fontSize: 18,
+ fontWeight: 'bold',
+ textAlign: 'center',
+ },
+ paragraph: {
+ fontSize: 25,
+ textAlign: 'center',
+ },
+ buttonsColumn: {
+ gap: 16,
+ },
+});
+
+export default App;
+```
+
+---
+
+# 参考
+
+## 方法
+
+### `isEnabled()`
+
+```tsx
+static isEnabled(): boolean;
+```
+
+---
+
+### `beginEvent()`
+
+```tsx
+static beginEvent(eventName: string | (() => string), args?: EventArgs);
+```
+
+beginEvent/endEvent 用于在同一个调用栈帧内开始和结束性能分析。
+
+---
+
+### `endEvent()`
+
+```tsx
+static endEvent(args?: EventArgs);
+```
+
+---
+
+### `beginAsyncEvent()`
+
+```tsx
+static beginAsyncEvent(
+ eventName: string | (() => string),
+ args?: EventArgs,
+): number;
+```
+
+beginAsyncEvent/endAsyncEvent 用于开始和结束性能分析,其中结束可以发生在另一个线程上或在当前堆栈帧之外,例如 await。返回的 cookie 变量应该用作 endAsyncEvent 调用的输入以结束性能分析。
+
+---
+
+### `endAsyncEvent()`
+
+```tsx
+static endAsyncEvent(
+ eventName: EventName,
+ cookie: number,
+ args?: EventArgs,
+);
+```
+
+---
+
+### `counterEvent()`
+
+```tsx
+static counterEvent(eventName: string | (() => string), value: number);
+```
+
+将值注册到 systrace 时间线上的 profileName。
diff --git a/cnwebsite/versioned_docs/version-0.85/targetevent.md b/cnwebsite/versioned_docs/version-0.85/targetevent.md
new file mode 100644
index 00000000000..758a615095f
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/targetevent.md
@@ -0,0 +1,29 @@
+---
+id: targetevent
+title: TargetEvent 对象类型
+---
+
+`TargetEvent` 对象作为焦点变化的结果在回调中返回,例如 [TextInput](textinput) 组件中的 `onFocus` 或 `onBlur`。
+
+## 示例
+
+```
+{
+ target: 1127
+}
+```
+
+## 属性与值
+
+### `target`
+
+接收 TargetEvent 的元素的节点 ID。
+
+| 类型 | 可选 |
+| --------------------------- | ---- |
+| number, `null`, `undefined` | 否 |
+
+## 被下列组件引用
+
+- [`TextInput`](textinput)
+- [`TouchableWithoutFeedback`](touchablewithoutfeedback)
diff --git a/cnwebsite/versioned_docs/version-0.85/testing-overview.md b/cnwebsite/versioned_docs/version-0.85/testing-overview.md
new file mode 100644
index 00000000000..a789ac9f47c
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/testing-overview.md
@@ -0,0 +1,287 @@
+---
+id: testing-overview
+title: Testing
+author: Vojtech Novak
+authorURL: 'https://twitter.com/vonovak'
+description: This guide introduces React Native developers to the key concepts behind testing, how to write good tests, and what kinds of tests you can incorporate into your workflow.
+---
+
+随着代码库的扩展,你意想不到的小错误和边缘情况可能会引发更大的失败。错误会导致糟糕的用户体验,最终导致业务损失。一种防止脆弱编程的方法是在发布到生产环境之前测试你的代码。
+
+在本指南中,我们将介绍不同的自动化方法,从静态分析到端到端测试,以确保你的应用按预期工作。
+
+
+
+## 为什么测试
+
+我们都是人类,人类会犯错误。测试很重要,因为它可以帮助你发现这些错误,并验证你的代码是否按预期工作。也许更重要的是,测试确保了你的代码在添加新功能、重构现有代码或升级项目的主要依赖项时继续按预期工作。
+
+测试比你想象的更有价值。修复代码中错误的一种最佳方法是编写一个失败的测试来暴露它。然后当你修复错误并重新运行测试时,如果测试通过,则意味着错误已修复,不会再次引入代码库。
+
+测试还可以作为新加入团队的人的文档。对于从未见过代码库的人来说,阅读测试可以帮助他们理解现有代码的工作原理。
+
+最后但并非最不重要的是,更多的自动化测试意味着更少的时间用于手动 QA ,节省了宝贵的时间。
+
+## 静态分析
+
+提高代码质量的第一步是开始使用静态分析工具。静态分析在编写代码时检查代码错误,但不会运行任何代码。
+
+- **Linters** 分析代码以捕获常见的错误,如未使用的代码,并帮助避免使用 tabs 而不是 spaces 等风格指南的错误。
+- **Type checking** 确保传递给函数的构造与函数设计接受的构造匹配,例如传递一个字符串到期望一个数字的计数函数。
+
+React Native 自带两种这样的工具:[ESLint](https://eslint.org/) 用于 linting,[TypeScript](typescript) 用于类型检查。
+
+## 编写可测试的代码
+
+要开始测试,你首先需要编写可测试的代码。考虑一个飞机制造过程--在任何模型首次起飞以展示其复杂系统是否正常工作之前,各个部件都经过测试,以确保它们安全且正常工作。例如,机翼在极端负载下被弯曲测试;发动机部件被测试其耐用性;挡风玻璃被测试以模拟鸟类撞击。
+
+软件开发也是如此。与将整个程序写在一个巨大的文件中,不如将代码写成多个小模块,这些模块可以更彻底地测试,而不是测试整个程序。这样,编写可测试的代码与编写干净、模块化的代码是相辅相成的。
+
+为了使你的应用更易于测试,首先将你的应用的视图部分--你的 React 组件--与你的业务逻辑和应用状态分离(无论你使用的是 Redux、MobX 还是其他解决方案)。这样,你可以将业务逻辑的测试--不应依赖于你的 React 组件--与组件本身独立开来,组件的主要工作是渲染你的应用的 UI!
+
+理论上,你可以将所有逻辑和数据获取从你的组件中移出。这样你的组件将专门用于渲染。你的状态将完全独立于你的组件。你的应用的逻辑将完全不依赖于任何 React 组件!
+
+:::tip
+我们鼓励你进一步探索可测试代码的主题,在其他学习资源中。
+:::
+
+## 编写测试
+
+编写可测试的代码后,就可以编写一些实际的测试了!React Native 的默认模板附带 [Jest](https://jestjs.io) 测试框架。它包括一个针对此环境的预设,因此你可以在不进行配置调整的情况下快速上手--稍后将介绍[模拟](#mocking)。你可以使用 Jest 编写本指南中提到的所有类型的测试。
+
+:::note
+如果你进行测试驱动开发,你实际上是先编写测试!这样,代码的可测试性就得到了保证。
+:::
+
+### 结构化测试
+
+你的测试应该简短且理想情况下只测试一件事。让我们从一个用 Jest 编写的示例单元测试开始:
+
+```js
+it('given a date in the past, colorForDueDate() returns red', () => {
+ expect(colorForDueDate('2000-10-20')).toBe('red');
+});
+```
+
+测试由传递给 [`it`](https://jestjs.io/docs/en/api#testname-fn-timeout) 函数的字符串描述。请仔细编写描述,以便清楚地说明正在测试的内容。尽你所能覆盖以下内容:
+
+1. **Given** - 一些预条件
+2. **When** - 由正在测试的函数执行的动作
+3. **Then** - 预期的结果
+
+这被称为 AAA(安排、行动、断言)。
+
+Jest 提供了 [`describe`](https://jestjs.io/docs/en/api#describename-fn) 函数来帮助结构化你的测试。使用 `describe` 将属于一个功能的所有测试组合在一起。如果需要,描述可以嵌套。你还会经常使用 [`beforeEach`](https://jestjs.io/docs/en/api#beforeeachfn-timeout) 或 [`beforeAll`](https://jestjs.io/docs/en/api#beforeallfn-timeout) 来设置正在测试的对象。更多信息请参阅 [Jest api 参考](https://jestjs.io/docs/en/api)。
+
+如果你的测试有很多步骤或很多期望,你可能需要将其拆分为多个更小的测试。同样,确保你的测试完全独立于其他测试。你的测试套件中的每个测试必须可以单独执行,而无需先运行其他测试。相反,如果你一起运行所有测试,第一个测试不能影响第二个测试的输出。
+
+最后,作为开发人员,我们喜欢我们的代码工作良好且不崩溃。有了测试,这通常是相反的。将失败的测试视为 _好事情_!当测试失败时,通常意味着某些事情不正确。这给你一个机会在影响用户之前修复问题。
+
+## 单元测试
+
+单元测试覆盖代码的最小部分,如单个函数或类。
+
+当正在测试的对象有任何依赖项时,你通常需要模拟它们,如下一节所述。
+
+单元测试的优点是它们写起来很快,运行也很快。因此,在你工作时,你可以快速获得测试是否通过的反馈。Jest 甚至有一个选项可以持续运行与正在编辑的代码相关的测试:[Watch mode](https://jestjs.io/docs/en/cli#watch)。
+
+
+
+### 模拟
+
+有时,当正在测试的对象有外部依赖项时,你可能需要"模拟"它们。"模拟"是指用你自己的实现替换代码的某些依赖项。
+
+:::info
+通常,在测试中使用真实对象比使用模拟更好,但有时这是不可能的。例如:当你的 JS 单元测试依赖于用 Java 或 Objective-C 编写的原生模块时。
+:::
+
+想象你正在编写一个显示你所在城市当前天气的应用,并且你正在使用一个提供天气信息的外部服务或其他依赖项。如果服务告诉你正在下雨,你想要显示一张带有雨云的图片。你不想在测试中调用那个服务,因为:
+
+- 它会使测试变慢和不稳定(因为涉及网络请求)
+- 服务每次运行测试时可能会返回不同的数据
+- 第三方服务可以在你真正需要运行测试时离线!
+
+因此,你可以提供一个服务的模拟实现,有效地替换数千行代码和一些连接互联网的温度计!
+
+:::note
+Jest 从函数到模块级别都支持[模拟](https://jestjs.io/docs/en/mock-functions#mocking-modules)。
+:::
+
+## 集成测试
+
+在编写较大的软件系统时,其中的各个部分需要相互交互。在单元测试中,如果你的单元依赖于另一个单元,你有时会模拟依赖项,用一个假的单元替换它。
+
+在集成测试中,真正的单元被组合在一起(与你的应用相同),并一起测试以确保它们协作正常。这不是说模拟不会在这里发生:你仍然需要模拟(例如,模拟与天气服务的通信),但与单元测试相比,需要的模拟要少得多。
+
+:::info
+请注意,关于集成测试的术语并不总是一致的。同样,单元测试和集成测试之间的界限并不总是清晰的。对于本指南,如果你的测试符合以下条件,则属于"集成测试":
+
+- 组合了你的应用的几个模块(如上所述)
+- 使用外部系统
+- 对其他应用(如天气服务 API)进行网络调用
+- 进行任何类型的文件或数据库 I/O 操作
+ :::
+
+
+
+## 组件测试
+
+React 组件负责渲染你的应用,用户将直接与它们交互。即使你的应用的业务逻辑有很高的测试覆盖率并且是正确的,没有组件测试,你仍然可能向用户交付一个损坏的 UI。组件测试可以属于单元测试和集成测试,但由于它们是 React Native 的核心部分,我们将它们单独介绍。
+
+对于测试 React 组件,你可能会想要测试以下内容:
+
+- 交互:确保组件在用户交互时正确行为(例如,当用户按下按钮时)
+- 渲染:确保组件的渲染输出正确(例如,按钮的外观和在 UI 中的位置)
+
+例如,如果你有一个带有 `onPress` 监听器的按钮,你想要测试按钮是否正确显示,并且点击按钮时组件能够正确处理。
+
+有几个库可以帮助你进行这些测试:
+
+- React 的 [Test Renderer](https://reactjs.org/docs/test-renderer.html),与核心一起开发,提供了一个 React 渲染器,可以用来将 React 组件渲染为纯 JavaScript 对象,而不依赖于 DOM 或原生移动环境。
+- [React Native Testing Library](https://callstack.github.io/react-native-testing-library/) 建立在 React 的测试渲染器之上,并添加了本段中描述的 `fireEvent` 和 `query` API。
+
+:::warning
+组件测试仅在 Node.js 环境中运行。它们不考虑任何 iOS、Android 或其他平台代码,这些代码支持 React Native 组件。因此,它们不能给你 100% 的信心确保一切正常工作。如果 iOS 或 Android 代码中存在错误,它们将无法找到。
+:::
+
+
+
+### 测试用户交互
+
+除了渲染一些 UI,你的组件处理诸如 `TextInput` 的 `onChangeText` 或 `Button` 的 `onPress` 等事件。它们可能还包含其他函数和事件回调。考虑以下示例:
+
+```tsx
+function GroceryShoppingList() {
+ const [groceryItem, setGroceryItem] = useState('');
+ const [items, setItems] = useState([]);
+
+ const addNewItemToShoppingList = useCallback(() => {
+ setItems([groceryItem, ...items]);
+ setGroceryItem('');
+ }, [groceryItem, items]);
+
+ return (
+ <>
+ setGroceryItem(text)}
+ />
+
+ {items.map(item => (
+ {item}
+ ))}
+ >
+ );
+}
+```
+
+当测试用户交互时,从用户的角度测试组件--页面上有什么?交互时有什么变化?
+
+作为一个经验法则,优先使用用户可以看到或听到的内容:
+
+- 使用渲染的文本或 [accessibility helpers](https://reactnative.dev/docs/accessibility#accessibility-properties) 进行断言
+
+相反,你应该避免:
+
+- 对组件的 props 或状态进行断言
+- 基于 testID 的查询
+
+避免测试实现细节,如 props 或状态--虽然这些测试有效,但它们不是面向用户如何与组件交互的,并且容易在重构时(例如,当你想要重命名某些内容或重写使用 Hooks 的类组件时)失效。
+
+:::info
+类组件特别容易测试其实现细节,如内部状态、props 或事件处理程序。为了避免测试实现细节,优先使用带有 Hooks 的函数组件,这使得依赖组件内部变得困难。
+:::
+
+组件测试库,如 [React Native Testing Library](https://callstack.github.io/react-native-testing-library/),通过仔细选择提供的 API 来促进编写用户中心的测试。以下示例使用 `fireEvent` 方法 `changeText` 和 `press` 来模拟用户与组件的交互,并使用 `getAllByText` 查询函数来找到渲染输出中匹配的 `Text` 节点。
+
+```tsx
+test('given empty GroceryShoppingList, user can add an item to it', () => {
+ const {getByPlaceholderText, getByText, getAllByText} = render(
+ ,
+ );
+
+ fireEvent.changeText(
+ getByPlaceholderText('Enter grocery item'),
+ 'banana',
+ );
+ fireEvent.press(getByText('Add the item to list'));
+
+ const bananaElements = getAllByText('banana');
+ expect(bananaElements).toHaveLength(1); // expect 'banana' to be on the list
+});
+```
+
+这个示例不是测试当调用某个函数时某些状态的变化。它测试的是当用户在 `TextInput` 中更改文本并按下 `Button` 时会发生什么!
+
+### 测试渲染输出
+
+[快照测试](https://jestjs.io/docs/en/snapshot-testing) 是 Jest 启用的先进测试类型。它是一个非常强大且低级别的工具,因此在使用时需要额外注意。
+
+一个"组件快照"是一个由 Jest 内置的 React 序列化器创建的 JSX 字符串。这个序列化器让 Jest 能够将 React 组件树转换为人类可读的字符串。换句话说:组件快照是组件渲染输出的文本表示,在测试运行期间生成。它可能看起来像这样:
+
+```tsx
+
+ Welcome to React Native!
+
+```
+
+使用快照测试时,通常首先实现组件,然后运行快照测试。快照测试然后创建一个快照,并将其保存到你的仓库中的参考快照文件中。**然后提交并检查该文件**。任何对组件渲染输出的未来更改都会更改其快照,这将导致测试失败。然后你需要更新测试的存储参考快照以通过测试。该更改再次需要提交和审查。
+
+快照有几个弱点:
+
+- 对于你作为开发人员或审阅者来说,很难判断快照中的变化是否是有意为之,还是错误的证据。尤其是大型快照很快变得难以理解,其价值变得很低。
+- 当快照创建时,此时它被认为是正确的--即使渲染输出实际上是错误的。
+- 当快照失败时,使用 `--updateSnapshot` jest 选项更新它而不采取适当措施调查更改是否是预期的,这是诱人的。因此需要一定的开发纪律。
+
+快照本身并不能确保你的组件渲染逻辑是正确的,它们只是很好地守护着意外的变化,并检查测试的 React 树下的组件是否接收了预期的 props(样式等)。
+
+我们建议你只使用小的快照(见 [`no-large-snapshots` 规则](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/no-large-snapshots.md))。如果你想要测试两个 React 组件状态之间的变化,使用 [`snapshot-diff`](https://github.com/jest-community/snapshot-diff)。在不确定的情况下,优先使用前面段落中描述的显式期望。
+
+
+
+## 端到端测试
+
+在端到端(E2E)测试中,尝试从用户的角度来验证应用在设备(或模拟器 / 模拟器)上的工作情况。
+
+这是通过在发布配置中构建应用并运行测试来完成的。在 E2E 测试中,你不再考虑 React 组件、React Native API、Redux 存储或任何业务逻辑。这不是 E2E 测试的目的,这些在 E2E 测试期间甚至对你不可用。
+
+相反,E2E 测试库允许你找到并控制应用屏幕上的元素:例如,你可以 _实际地_ 点击按钮或像真实用户一样在 `TextInputs` 中插入文本。然后你可以做出关于某个元素是否存在于应用的屏幕上、是否可见、包含什么文本等的断言。
+
+E2E 测试给你最高的信心,部分应用正在工作。权衡包括:
+
+- 编写它们比其他类型的测试更耗时
+- 它们运行得更慢
+- 它们更容易出现"flaky"(一个"flaky"测试是随机通过和失败的测试,没有任何代码更改)
+
+尝试用 E2E 测试覆盖应用的关键部分:认证流程、核心功能、支付等。对于应用的非关键部分,使用更快的 JS 测试。你添加的测试越多,你的信心就越高,但同时,你维护和运行它们的成本也越高。考虑权衡,并决定什么最适合你。
+
+有几种 E2E 测试工具可用:在 React Native 社区中,[Detox](https://github.com/wix/detox/) 是一个流行的框架,因为它专为 React Native 应用设计。另一个流行的库是 [Appium](https://appium.io/) 或 [Maestro](https://maestro.mobile.dev/)。
+
+
+
+## 总结
+
+我们希望你享受阅读并从本指南中学习到一些东西。有很多方法可以测试你的应用。一开始可能很难决定使用什么。然而,我们相信一旦你开始为你的优秀 React Native 应用添加测试,一切都会变得有意义。所以,你还在等什么?提高你的覆盖率!
+
+### 链接
+
+- [React 测试概述](https://reactjs.org/docs/testing.html)
+- [React Native Testing Library](https://callstack.github.io/react-native-testing-library/)
+- [Jest docs](https://jestjs.io/docs/en/tutorial-react-native)
+- [Detox](https://github.com/wix/detox/)
+- [Appium](https://appium.io/)
+- [Maestro](https://maestro.mobile.dev/)
+
+---
+
+_This guide originally authored and contributed in full by [Vojtech Novak](https://twitter.com/vonovak)._
diff --git a/cnwebsite/versioned_docs/version-0.85/text-nodes.md b/cnwebsite/versioned_docs/version-0.85/text-nodes.md
new file mode 100644
index 00000000000..7bc1a9e2a3a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/text-nodes.md
@@ -0,0 +1,86 @@
+---
+id: text-nodes
+title: 文本节点
+---
+
+文本节点表示树中的原始文本内容(类似于 Web 上的 [`Text`](https://developer.mozilla.org/zh-CN/docs/Web/API/Text) 节点)。它们不能直接通过 `refs` 访问,但可以使用元素 refs 上的方法(如 [`childNodes`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/childNodes))来访问。
+
+```SnackPlayer ext=js&name=Text%20instances%20example
+import * as React from 'react';
+import { SafeAreaView, StyleSheet, Text } from 'react-native';
+
+const TextWithRefs = () => {
+ const ref = React.useRef(null);
+ const [viewInfo, setViewInfo] = React.useState('');
+
+ React.useEffect(() => {
+ // `textElement` 是实现此处描述的接口的对象。
+ const textElement = ref.current;
+ const textNode = textElement.childNodes[0];
+ setViewInfo(
+ `Text content is: ${textNode.nodeValue}`,
+ );
+ }, []);
+
+ return (
+
+
+ Hello world!
+
+ {viewInfo}
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ content: {
+ padding: 10,
+ backgroundColor: 'gray',
+ },
+});
+
+export default TextWithRefs;
+```
+
+---
+
+## 参考
+
+### Web 兼容 API
+
+来自 [`CharacterData`](https://developer.mozilla.org/zh-CN/docs/Web/API/CharacterData):
+
+- 属性
+ - [`data`](https://developer.mozilla.org/zh-CN/docs/Web/API/CharacterData/data)
+ - [`length`](https://developer.mozilla.org/zh-CN/docs/Web/API/CharacterData/length)
+ - [`nextElementSibling`](https://developer.mozilla.org/zh-CN/docs/Web/API/CharacterData/nextElementSibling)
+ - [`previousElementSibling`](https://developer.mozilla.org/zh-CN/docs/Web/API/CharacterData/previousElementSibling)
+- 方法
+ - [`substringData()`](https://developer.mozilla.org/zh-CN/docs/Web/API/CharacterData/substringData)
+
+来自 [`Node`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node):
+
+- 属性
+ - [`childNodes`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/childNodes)
+ - [`firstChild`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/firstChild)
+ - [`isConnected`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/isConnected)
+ - [`lastChild`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/lastChild)
+ - [`nextSibling`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nextSibling)
+ - [`nodeName`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeName)
+ - [`nodeType`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeType)
+ - [`nodeValue`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/nodeValue)
+ - [`ownerDocument`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/ownerDocument)
+ - ℹ️ 将返回渲染此组件的[文档实例](/docs/next/document-instances)。
+ - [`parentElement`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/parentElement)
+ - [`parentNode`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/parentNode)
+ - [`previousSibling`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/previousSibling)
+ - [`textContent`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/textContent)
+- 方法
+ - [`compareDocumentPosition()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/compareDocumentPosition)
+ - [`contains()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/contains)
+ - [`getRootNode()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/getRootNode)
+ - ℹ️ 如果组件未挂载,将返回对自身的引用。
+ - [`hasChildNodes()`](https://developer.mozilla.org/zh-CN/docs/Web/API/Node/hasChildNodes)
diff --git a/cnwebsite/versioned_docs/version-0.85/text-style-props.md b/cnwebsite/versioned_docs/version-0.85/text-style-props.md
new file mode 100644
index 00000000000..66ed27059a9
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/text-style-props.md
@@ -0,0 +1,946 @@
+---
+id: text-style-props
+title: Text Style Props
+---
+
+### 示例
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+
+
+
+```SnackPlayer name=TextStyleProps&supportedPlatforms=ios,android&ext=js&dependencies=@react-native-community/slider
+import React, {useState} from 'react';
+import {
+ FlatList,
+ Platform,
+ ScrollView,
+ StyleSheet,
+ Switch,
+ Text,
+ TouchableWithoutFeedback,
+ View,
+} from 'react-native';
+import Slider from '@react-native-community/slider';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const fontStyles = ['normal', 'italic'];
+const fontVariants = [
+ undefined,
+ 'small-caps',
+ 'oldstyle-nums',
+ 'lining-nums',
+ 'tabular-nums',
+ 'proportional-nums',
+];
+const fontWeights = [
+ 'normal',
+ 'bold',
+ '100',
+ '200',
+ '300',
+ '400',
+ '500',
+ '600',
+ '700',
+ '800',
+ '900',
+];
+const textAlignments = ['auto', 'left', 'right', 'center', 'justify'];
+const textDecorationLines = [
+ 'none',
+ 'underline',
+ 'line-through',
+ 'underline line-through',
+];
+const textDecorationStyles = ['solid', 'double', 'dotted', 'dashed'];
+const textTransformations = ['none', 'uppercase', 'lowercase', 'capitalize'];
+const textAlignmentsVertical = ['auto', 'top', 'bottom', 'center'];
+const writingDirections = ['auto', 'ltr', 'rtl'];
+
+const App = () => {
+ const [fontSize, setFontSize] = useState(20);
+ const [fontStyleIdx, setFontStyleIdx] = useState(0);
+ const [fontWeightIdx, setFontWeightIdx] = useState(0);
+ const [lineHeight, setLineHeight] = useState(24);
+ const [textAlignIdx, setTextAlignIdx] = useState(0);
+ const [textDecorationLineIdx, setTextDecorationLineIdx] = useState(0);
+ const [includeFontPadding, setIncludeFontPadding] = useState(false);
+ const [textVerticalAlignIdx, setTextVerticalAlignIdx] = useState(0);
+ const [fontVariantIdx, setFontVariantIdx] = useState(0);
+ const [letterSpacing, setLetterSpacing] = useState(0);
+ const [textDecorationStyleIdx, setTextDecorationStyleIdx] = useState(0);
+ const [textTransformIdx, setTextTransformIdx] = useState(0);
+ const [writingDirectionIdx, setWritingDirectionIdx] = useState(0);
+ const [textShadowRadius, setTextShadowRadius] = useState(0);
+ const [textShadowOffset, setTextShadowOffset] = useState({
+ height: 0,
+ width: 0,
+ });
+
+ const [, ...validFontVariants] = fontVariants;
+
+ return (
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting
+ industry. 112 Likes
+
+
+
+
+ Common platform properties
+
+ setTextShadowOffset(prev => ({...prev, height: val}))
+ }
+ />
+
+ setTextShadowOffset(prev => ({...prev, width: val}))
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+ {Platform.OS === 'android' && (
+
+
+ Android only properties
+
+
+
+
+ )}
+ {Platform.OS === 'ios' && (
+
+
+ iOS only properties
+
+
+
+
+ )}
+
+
+
+ );
+};
+
+const CustomSwitch = ({label, handleValueChange, value}) => {
+ return (
+ <>
+ {label}
+
+
+
+ >
+ );
+};
+
+const CustomSlider = ({
+ label,
+ handleValueChange,
+ step = 1,
+ minimumValue = 0,
+ maximumValue = 10,
+ value,
+}) => {
+ return (
+ <>
+ {label && (
+ {`${label} (${value.toFixed(2)})`}
+ )}
+
+
+
+ >
+ );
+};
+
+const CustomPicker = ({label, data, currentIndex, onSelected}) => {
+ return (
+ <>
+ {label}
+
+ String(item)}
+ renderItem={({item, index}) => {
+ const selected = index === currentIndex;
+ return (
+ onSelected(index)}>
+
+
+ {item + ''}
+
+
+
+ );
+ }}
+ />
+
+ >
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ pargraphWrapper: {
+ backgroundColor: 'black',
+ },
+ paragraph: {
+ color: '#fff',
+ textDecorationColor: 'yellow',
+ textShadowColor: 'red',
+ textShadowRadius: 1,
+ padding: 24,
+ },
+ wrapperHorizontal: {
+ justifyContent: 'center',
+ color: 'black',
+ },
+ itemStyleHorizontal: {
+ marginRight: 10,
+ height: 50,
+ padding: 8,
+ borderWidth: 1,
+ borderColor: 'grey',
+ borderRadius: 8,
+ textAlign: 'center',
+ justifyContent: 'center',
+ },
+ itemSelectedStyleHorizontal: {
+ borderWidth: 2,
+ borderColor: '#06bcee',
+ },
+ platformContainer: {
+ marginTop: 8,
+ borderTopWidth: 1,
+ },
+ platformContainerTitle: {
+ marginTop: 8,
+ },
+ title: {
+ fontWeight: 'bold',
+ marginVertical: 8,
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=TextStyleProps&supportedPlatforms=ios,android&ext=tsx&dependencies=@react-native-community/slider
+import React, {useState} from 'react';
+import {
+ FlatList,
+ Platform,
+ ScrollView,
+ StyleSheet,
+ Switch,
+ Text,
+ TouchableWithoutFeedback,
+ View,
+ TextStyle,
+} from 'react-native';
+import Slider from '@react-native-community/slider';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const App = () => {
+ const [fontSize, setFontSize] = useState(20);
+ const [fontStyleIdx, setFontStyleIdx] = useState(0);
+ const [fontWeightIdx, setFontWeightIdx] = useState(0);
+ const [lineHeight, setLineHeight] = useState(24);
+ const [textAlignIdx, setTextAlignIdx] = useState(0);
+ const [textDecorationLineIdx, setTextDecorationLineIdx] = useState(0);
+ const [includeFontPadding, setIncludeFontPadding] = useState(false);
+ const [textVerticalAlignIdx, setTextVerticalAlignIdx] = useState(0);
+ const [fontVariantIdx, setFontVariantIdx] = useState(0);
+ const [letterSpacing, setLetterSpacing] = useState(0);
+ const [textDecorationStyleIdx, setTextDecorationStyleIdx] = useState(0);
+ const [textTransformIdx, setTextTransformIdx] = useState(0);
+ const [writingDirectionIdx, setWritingDirectionIdx] = useState(0);
+ const [textShadowRadius, setTextShadowRadius] = useState(0);
+ const [textShadowOffset, setTextShadowOffset] = useState({
+ height: 0,
+ width: 0,
+ });
+
+ const [, ...validFontVariants] = fontVariants;
+
+ return (
+
+
+
+
+ Lorem Ipsum is simply dummy text of the printing and typesetting
+ industry. 112 Likes
+
+
+
+
+ Common platform properties
+
+ setTextShadowOffset(prev => ({...prev, height: val}))
+ }
+ />
+
+ setTextShadowOffset(prev => ({...prev, width: val}))
+ }
+ />
+
+
+
+
+
+
+
+
+
+
+
+ {Platform.OS === 'android' && (
+
+
+ Android only properties
+
+
+
+
+ )}
+ {Platform.OS === 'ios' && (
+
+
+ iOS only properties
+
+
+
+
+ )}
+
+
+
+ );
+};
+
+type CustomSwitchProps = {
+ label: string;
+ value: boolean;
+ handleValueChange: (value: boolean) => void;
+};
+
+const CustomSwitch = ({label, handleValueChange, value}: CustomSwitchProps) => {
+ return (
+ <>
+ {label}
+
+
+
+ >
+ );
+};
+
+type CustomSliderProps = {
+ label: string;
+ value: number;
+ handleValueChange: (value: number) => void;
+ step?: number;
+ minimumValue?: number;
+ maximumValue?: number;
+};
+
+const CustomSlider = ({
+ label,
+ handleValueChange,
+ step = 1,
+ minimumValue = 0,
+ maximumValue = 10,
+ value,
+}: CustomSliderProps) => {
+ return (
+ <>
+ {label && (
+ {`${label} (${value.toFixed(2)})`}
+ )}
+
+
+
+ >
+ );
+};
+
+type CustomPickerProps = {
+ label: string;
+ data?: ArrayLike | null;
+ currentIndex: number;
+ onSelected: (index: number) => void;
+};
+
+const CustomPicker = ({
+ label,
+ data,
+ currentIndex,
+ onSelected,
+}: CustomPickerProps) => {
+ return (
+ <>
+ {label}
+
+ String(item)}
+ renderItem={({item, index}: {item: string; index: number}) => {
+ const selected = index === currentIndex;
+ return (
+ onSelected(index)}>
+
+
+ {item + ''}
+
+
+
+ );
+ }}
+ />
+
+ >
+ );
+};
+
+const fontStyles = ['normal', 'italic'];
+const fontVariants = [
+ undefined,
+ 'small-caps',
+ 'oldstyle-nums',
+ 'lining-nums',
+ 'tabular-nums',
+ 'proportional-nums',
+];
+const fontWeights = [
+ 'normal',
+ 'bold',
+ '100',
+ '200',
+ '300',
+ '400',
+ '500',
+ '600',
+ '700',
+ '800',
+ '900',
+];
+const textAlignments = ['auto', 'left', 'right', 'center', 'justify'];
+const textDecorationLines = [
+ 'none',
+ 'underline',
+ 'line-through',
+ 'underline line-through',
+];
+const textDecorationStyles = ['solid', 'double', 'dotted', 'dashed'];
+const textTransformations = ['none', 'uppercase', 'lowercase', 'capitalize'];
+const textAlignmentsVertical = ['auto', 'top', 'bottom', 'center'];
+const writingDirections = ['auto', 'ltr', 'rtl'];
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ pargraphWrapper: {
+ backgroundColor: 'black',
+ },
+ paragraph: {
+ color: '#fff',
+ textDecorationColor: 'yellow',
+ textShadowColor: 'red',
+ textShadowRadius: 1,
+ padding: 24,
+ },
+ wrapperHorizontal: {
+ justifyContent: 'center',
+ color: 'black',
+ },
+ itemStyleHorizontal: {
+ marginRight: 10,
+ height: 50,
+ padding: 8,
+ borderWidth: 1,
+ borderColor: 'grey',
+ borderRadius: 8,
+ textAlign: 'center',
+ justifyContent: 'center',
+ },
+ itemSelectedStyleHorizontal: {
+ borderWidth: 2,
+ borderColor: '#06bcee',
+ },
+ platformContainer: {
+ marginTop: 8,
+ borderTopWidth: 1,
+ },
+ platformContainerTitle: {
+ marginTop: 8,
+ },
+ title: {
+ fontWeight: 'bold',
+ marginVertical: 8,
+ },
+});
+
+export default App;
+```
+
+
+
+
+# 参考文档
+
+## Props
+
+### `color`
+
+| 类型 |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `fontFamily`
+
+| 类型 |
+| ------ |
+| string |
+
+iOS 上支持通用字体族 `system-ui`、`ui-sans-serif`、`ui-serif`、`ui-monospace` 和 `ui-rounded`。
+
+---
+
+### `fontSize`
+
+| 类型 |
+| ------ |
+| number |
+
+---
+
+### `fontStyle`
+
+| 类型 |
+| ---------------------------- |
+| enum(`'normal'`, `'italic'`) |
+
+---
+
+### `fontWeight`
+
+指定字体粗细。大多数字体支持 `'normal'` 和 `'bold'` 值。并非所有字体都有每个数值对应的变体,在这种情况下会选择最接近的值。
+
+| 类型 | 默认值 |
+| --------------------------------------------------------------------------------------------------------------------- | ---------- |
+| enum(`'normal'`, `'bold'`, `'100'`, `'200'`, `'300'`, `'400'`, `'500'`, `'600'`, `'700'`, `'800'`, `'900'`) or number | `'normal'` |
+
+---
+
+### `includeFontPadding` Android
+
+设置为 `false` 可移除为某些升部/降部预留的额外字体内边距。在某些字体下,此内边距可能导致文本在垂直居中时看起来略微偏移。为获得最佳效果,建议同时将 `textAlignVertical` 设置为 `center`。
+
+| 类型 | 默认值 |
+| ---- | ------ |
+| bool | `true` |
+
+---
+
+### `fontVariant`
+
+允许你设置字体的所有变体。可以通过枚举数组或空格分隔的字符串来设置,例如 `'small-caps common-ligatures'`。
+
+| 类型 | 默认值 |
+| -------------------------------------------------------------------------------------------------------------------- | ------ |
+| array of enum(`'small-caps'`, `'oldstyle-nums'`, `'lining-nums'`, `'tabular-nums'`, `'proportional-nums'`) or string | `[]` |
+
+---
+
+### `letterSpacing`
+
+增加或减少字符间距。默认没有额外的字母间距。
+
+| 类型 |
+| ------ |
+| number |
+
+---
+
+### `lineHeight`
+
+控制文本元素中行间垂直间距的数值。指定连续文本行基线之间的距离。
+
+| 类型 |
+| ------ |
+| number |
+
+---
+
+### `textAlign`
+
+指定文本对齐方式。在 Android 上,`'justify'` 值仅在 Oreo(8.0)及以上版本(API 级别 >= 26)上支持。在更低版本的 Android 上会回退为 `left`。
+
+| 类型 | 默认值 |
+| ------------------------------------------------------------ | -------- |
+| enum(`'auto'`, `'left'`, `'right'`, `'center'`, `'justify'`) | `'auto'` |
+
+---
+
+### `textAlignVertical` Android
+
+| 类型 | 默认值 |
+| ----------------------------------------------- | -------- |
+| enum(`'auto'`, `'top'`, `'bottom'`, `'center'`) | `'auto'` |
+
+---
+
+### `textDecorationColor` iOS
+
+| 类型 |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `textDecorationLine`
+
+| 类型 | 默认值 |
+| --------------------------------------------------------------------------- | -------- |
+| enum(`'none'`, `'underline'`, `'line-through'`, `'underline line-through'`) | `'none'` |
+
+---
+
+### `textDecorationStyle` iOS
+
+| 类型 | 默认值 |
+| --------------------------------------------------- | --------- |
+| enum(`'solid'`, `'double'`, `'dotted'`, `'dashed'`) | `'solid'` |
+
+---
+
+### `textShadowColor`
+
+| 类型 |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `textShadowOffset`
+
+| 类型 |
+| ------------------------------------------- |
+| object: `{width?: number, height?: number}` |
+
+---
+
+### `textShadowRadius`
+
+| 类型 |
+| ------ |
+| number |
+
+---
+
+### `textTransform`
+
+| 类型 | 默认值 |
+| ------------------------------------------------------------ | -------- |
+| enum(`'none'`, `'uppercase'`, `'lowercase'`, `'capitalize'`) | `'none'` |
+
+---
+
+### `verticalAlign` Android
+
+| 类型 | 默认值 |
+| ----------------------------------------------- | -------- |
+| enum(`'auto'`, `'top'`, `'bottom'`, `'middle'`) | `'auto'` |
+
+---
+
+### `writingDirection` iOS
+
+| 类型 | 默认值 |
+| -------------------------------- | -------- |
+| enum(`'auto'`, `'ltr'`, `'rtl'`) | `'auto'` |
+
+---
+
+### `userSelect`
+
+允许用户选择文本并使用原生的复制粘贴功能。优先级高于 `selectable` 属性。
+
+| 类型 | 默认值 |
+| -------------------------------------------------------- | ------ |
+| enum(`'auto'`, `'text'`, `'none'`, `'contain'`, `'all'`) | `none` |
diff --git a/cnwebsite/versioned_docs/version-0.85/text.md b/cnwebsite/versioned_docs/version-0.85/text.md
new file mode 100644
index 00000000000..96355d6ac8a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/text.md
@@ -0,0 +1,781 @@
+---
+id: text
+title: Text
+---
+
+一个用于显示文本的 React 组件。
+
+`Text`支持嵌套、样式,以及触摸处理。
+
+在下面的例子里,嵌套的标题和正文文字会继承来自`styles.baseText`的`fontFamily`字体样式,不过标题上还附加了它自己额外的样式。标题和文本会在顶部依次堆叠,并且被代码中内嵌的换行符分隔开:
+
+```SnackPlayer name=Text%20Function%20Component%20Example
+import React, {useState} from 'react';
+import {Text, StyleSheet} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const TextInANest = () => {
+ const [titleText, setTitleText] = useState("Bird's Nest");
+ const bodyText = 'This is not really a bird nest.';
+
+ const onPressTitle = () => {
+ setTitleText("Bird's Nest [pressed]");
+ };
+
+ return (
+
+
+
+
+ {titleText}
+ {'\n'}
+ {'\n'}
+
+ {bodyText}
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ baseText: {
+ fontFamily: 'Cochin',
+ },
+ titleText: {
+ fontSize: 20,
+ fontWeight: 'bold',
+ },
+});
+
+export default TextInANest;
+```
+
+## 嵌套文本
+
+在 iOS 和 Android 中显示格式化文本的方法类似,都是提供你想显示的文本内容,然后使用范围标注来指定一些格式(在 iOS 上是用`NSAttributedString`,Android 上则是`SpannableString`)。这种用法非常繁琐。在 React Native 中,我们决定采用和 Web 一致的设计,这样你可以把相同格式的文本嵌套包裹起来:
+
+```SnackPlayer name=Nested%20Text%20Example
+import React from 'react';
+import {Text, StyleSheet} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const BoldAndBeautiful = () => (
+
+
+
+ I am bold
+ and red
+
+
+
+);
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ },
+ baseText: {
+ fontWeight: 'bold',
+ },
+ innerText: {
+ color: 'red',
+ },
+});
+
+export default BoldAndBeautiful;
+```
+
+而实际上在框架内部,这会生成一个扁平结构的`NSAttributedString`或是`SpannableString`,包含以下信息:
+
+```
+"I am bold and red"
+0-9: bold
+9-17: bold, red
+```
+
+## 容器
+
+``元素在布局上不同于其它组件:在 Text 内部的元素不再使用 flexbox 布局,而是采用文本布局。这意味着``内部的元素不再是一个个矩形,而可能会在行末进行折叠。
+
+```tsx
+
+ First part and
+ second part
+
+// Text container: the text will be inline, if the space allows it
+// |First part and second part|
+
+// otherwise, the text will flow as if it was one
+// |First part |
+// |and second |
+// |part |
+
+
+ First part and
+ second part
+
+// View container: each text is its own block
+// |First part and|
+// |second part |
+
+// otherwise, the text will flow in its own block
+// |First part |
+// |and |
+// |second part|
+```
+
+## 样式继承限制
+
+在 Web 上,要想指定整个文档的字体和大小,我们只需要写:
+
+```css
+html {
+ font-family:
+ 'lucida grande', tahoma, verdana, arial, sans-serif;
+ font-size: 11px;
+ color: #141823;
+}
+```
+
+当浏览器尝试渲染一个文本节点的时候,它会在树中一路向上查询,直到根节点,来找到一个具备`font-size`属性的元素。这个系统一个不好的地方在于**任何**节点都可能会有`font-size`属性,包括``标签。这个设计为了方便而设计,但实际上语义上并不太正确。
+
+在 React Native 中,我们把这个问题设计的更加严谨:**你必须把你的文本节点放在`
`组件内**。你不能直接在``下放置一段文本。
+
+```tsx
+// BAD: will raise exception, can't have a text node as child of a
+
+ Some text
+
+
+// GOOD
+
+
+ Some text
+
+
+```
+
+并且你也不能直接设置一整颗子树的默认样式。此外,`fontFamily`样式只接受一种字体名称,这一点和 CSS 也不一样。使用一个一致的文本和尺寸的推荐方式是创建一个包含相关样式的组件`MyAppText`,然后在你的 App 中反复使用它。你还可以创建更多特殊的组件譬如`MyAppHeaderText`来表达不同样式的文本。
+
+```tsx
+
+
+ Text styled with the default font for the entire application
+
+ Text styled as a header
+
+```
+
+假设`MyAppText`是一个组件,它简单地将其子元素渲染到一个带有样式的`Text`组件中,那么可以如下定义`MyAppHeaderText`:
+
+```tsx
+const MyAppHeaderText = ({children}) => {
+ return (
+
+ {children}
+
+ );
+};
+```
+
+以这种方式编写`MyAppText`确保我们能够从顶层组件获取样式,但同时也让我们有能力在特定用例中添加/覆盖它们。
+
+React Native 实际上还是有一部分样式继承的实现,不过仅限于文本标签的子树。在下面的代码里,第二部分会在加粗的同时又显示为红色:
+
+```tsx
+
+ I am bold
+ and red
+
+```
+
+我们相信这种看起来不太舒服的给文本添加样式的方法反而会帮助我们生产更好的 App:
+
+- (对开发者来说) React 组件在概念上被设计为强隔离性的:你应当可以在应用的任何位置放置一个组件,而且只要属性相同,其外观和表现都将完全相同。文本如果能够继承外面的样式属性,将会打破这种隔离性。
+
+- (对实现者来说) React Native 的实现也被简化了。我们不需要在每个元素上都添加一个`fontFamily`字段,并且我们也不需要隐含地在显示文本的时候向上遍历树。唯一的样式继承在原生 Text 组件中编码,也不会影响到其它组件或者系统本身。
+
+---
+
+# 文档
+
+## Props
+
+### `accessibilityHint`
+
+无障碍提示有助于用户理解在执行辅助功能元素上的操作时将会发生什么,尤其当这个结果在辅助功能标签中不明确时。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `accessibilityLanguage` iOS
+
+指示当用户与元素交互时屏幕阅读器应该使用哪种语言。它应该遵循[BCP 47 规范](https://www.rfc-editor.org/info/bcp47)。
+
+更多信息请参阅[iOS `accessibilityLanguage`文档](https://developer.apple.com/documentation/objectivec/nsobject/1615192-accessibilitylanguage)。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `accessibilityLabel`
+
+覆盖当用户与元素交互时屏幕阅读器读取的文本。默认情况下,标签是通过遍历所有子节点并累积所有的`Text`节点(以空格分隔)来构建的。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `accessibilityRole`
+
+告诉屏幕阅读器将当前聚焦的元素视为具有特定角色。
+
+在 iOS 上,这些角色映射到相应的辅助功能特征。图像按钮的功能与将特征设置为"图像"和"按钮"相同。有关更多信息,请查看[辅助功能指南](accessibility.md#accessibilitytraits-ios)。
+
+在 Android 上,这些角色在 TalkBack 上的类似功能就像在 iOS 的 Voiceover 上添加辅助功能特征一样。
+
+| Type |
+| ---------------------------------------------------- |
+| [AccessibilityRole](accessibility#accessibilityrole) |
+
+---
+
+### `accessibilityState`
+
+告诉屏幕阅读器将当前聚焦的元素视为处于特定状态。
+
+您可以提供一个状态,没有状态,或者多个状态。这些状态必须通过一个对象传递进来。例如:`{selected: true, disabled: true}`。
+
+| Type |
+| ------------------------------------------------------ |
+| [AccessibilityState](accessibility#accessibilitystate) |
+
+---
+
+### `accessibilityActions`
+
+无障碍操作允许辅助技术以编程方式调用组件的动作。`accessibilityActions`属性应包含动作对象的列表。每个动作对象都应包含字段名称和标签。
+
+更多信息请参阅[无障碍指南](accessibility.md#accessibility-actions)。
+
+| Type | Required |
+| ----- | -------- |
+| array | No |
+
+---
+
+### `onAccessibilityAction`
+
+当用户执行辅助功能操作时调用。此函数唯一的参数是一个包含要执行的操作名称的事件。
+
+有关详细信息,请参阅[辅助功能指南](accessibility.md#accessibility-actions)。
+
+| Type | Required |
+| -------- | -------- |
+| function | No |
+
+---
+
+### `accessible`
+
+当设置为 `true` 时,表示该视图是一个辅助功能元素。
+
+更多信息请参阅[辅助功能指南](accessibility#accessible-ios-android)。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `true` |
+
+---
+
+### `adjustsFontSizeToFit`
+
+指定字体是否随着给定样式的限制而自动缩放。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `false` |
+
+---
+
+### `allowFontScaling`
+
+控制字体是否要根据系统的"字体大小"辅助选项来进行缩放。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `true` |
+
+---
+
+### `android_hyphenationFrequency` Android
+
+设置在 Android API 级别 23+上确定单词断点时使用的自动连字符频率。
+
+| Type | Default |
+| ----------------------------------- | -------- |
+| enum(`'none'`, `'normal'`,`'full'`) | `'none'` |
+
+---
+
+### `aria-busy`
+
+表示某个元素正在被修改,辅助技术可能需要等待更改完成后再通知用户更新。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | false |
+
+---
+
+### `aria-checked`
+
+表示可选中元素的状态。此字段可以接受布尔值或字符串 "mixed" 来表示混合复选框。
+
+| Type | Default |
+| ---------------- | ------- |
+| boolean, 'mixed' | false |
+
+---
+
+### `aria-disabled`
+
+表示该元素是可感知的但被禁用,因此它不可编辑或不可操作。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | false |
+
+---
+
+### `aria-expanded`
+
+表示一个可展开的元素当前是展开还是折叠状态。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | false |
+
+---
+
+### `aria-label`
+
+定义一个用于标记交互元素的字符串值。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `aria-selected`
+
+表示一个可选择的元素当前是否被选中。
+
+| Type |
+| ------- |
+| boolean |
+
+### `dataDetectorType` Android
+
+确定文本元素中转换为可点击 URL 的数据类型。默认情况下,不检测任何数据类型。
+
+您只能提供一种类型。
+
+| Type | Default |
+| ------------------------------------------------------------- | -------- |
+| enum(`'phoneNumber'`, `'link'`, `'email'`, `'none'`, `'all'`) | `'none'` |
+
+---
+
+### `disabled` Android
+
+指定文本视图的禁用状态,用于测试目的。
+
+| Type | Default |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `dynamicTypeRamp` iOS
+
+在 iOS 上应用于此元素的[动态类型](https://developer.apple.com/documentation/uikit/uifont/scaling_fonts_automatically)坡度。
+
+| Type | Default |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------- | -------- |
+| enum(`'caption2'`, `'caption1'`, `'footnote'`, `'subheadline'`, `'callout'`, `'body'`, `'headline'`, `'title3'`, `'title2'`, `'title1'`, `'largeTitle'`) | `'body'` |
+
+---
+
+### `ellipsizeMode`
+
+当设置了`numberOfLines`时,此属性定义文本将如何被截断。`numberOfLines`必须与此属性一起设置。
+
+该属性有如下 4 种取值:
+
+- `head` - 从文本内容头部截取显示省略号。例如: "...wxyz"
+- `middle` - 在文本内容中间截取显示省略号。例如: "ab...yz"
+- `tail` - 从文本内容尾部截取显示省略号。例如: "abcd..."
+- `clip` - 不显示省略号,直接从尾部截断。
+
+:::note
+在 Android 上,当`numberOfLines`设置为大于`1`的值时,只有`tail`值才能正确工作。
+:::
+
+| Type | Default |
+| ---------------------------------------------- | ------- |
+| enum(`'head'`, `'middle'`, `'tail'`, `'clip'`) | `tail` |
+
+---
+
+### `id`
+
+用于从原生代码定位此视图。优先于`nativeID`属性。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `maxFontSizeMultiplier`
+
+指定当`allowFontScaling`启用时,字体可能达到的最大尺寸。可能的值包括:
+
+- `null/undefined`:从父节点或全局默认继承(0)
+- `0`:无最大值,忽略父级/全局默认
+- `>= 1`:将此节点的`maxFontSizeMultiplier`设置为此值
+
+| Type | Default |
+| ------ | ----------- |
+| number | `undefined` |
+
+---
+
+### `minimumFontScale`
+
+当`adjustsFontSizeToFit`开启时,指定字体可能达到的最小缩放比(值为 0.01-1.0)。
+
+| Type |
+| ------ |
+| number |
+
+---
+
+### `nativeID`
+
+用于在原生端定位此视图。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `numberOfLines`
+
+用来当文本过长的时候裁剪文本。包括折叠产生的换行在内,总的行数不会超过这个属性的限制。设置此属性为`0`将取消此限制,意味着不会应用行数限制。
+
+此属性一般和`ellipsizeMode`搭配使用。
+
+| Type | Default |
+| ------ | ------- |
+| number | `0` |
+
+---
+
+### `onLayout`
+
+在加载时或者布局变化以后调用。
+
+| Type |
+| -------------------------------------------------------- |
+| `md ({nativeEvent: [LayoutEvent](layoutevent)}) => void` |
+
+---
+
+### `onLongPress`
+
+当文本被长按以后调用此回调函数。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onMoveShouldSetResponder`
+
+此视图是否要"声明"触摸响应权?当该`View`不是响应者时,每次触摸移动都会调用此方法。
+
+| Type |
+| --------------------------------------------------------- |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => boolean` |
+
+---
+
+### `onPress`
+
+在用户按下后调用的函数,在`onPressOut`触发之后被触发。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onPressIn`
+
+在触摸开始时立即调用,早于`onPressOut`和`onPress`。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onPressOut`
+
+当触摸释放时调用。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onResponderGrant`
+
+该视图现在正在响应触摸事件。此时应该高亮显示,向用户表明正在发生什么。
+
+在 Android 上,从此回调返回 true 可以阻止任何其他原生组件成为响应者,直到此响应者终止。
+
+| Type |
+| ----------------------------------------------------------------- |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void | boolean` |
+
+---
+
+### `onResponderMove`
+
+用户正在移动手指。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onResponderRelease`
+
+触摸结束时触发。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onResponderTerminate`
+
+响应器已从`View`中移除。在调用`onResponderTerminationRequest`后可能会被其他视图获取,或者可能在没有询问的情况下被操作系统获取(例如,在 iOS 上发生在控制中心/通知中心)。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onResponderTerminationRequest`
+
+其他某个`View`想要成为响应者,并请求该`View`释放其响应者身份。返回`true`允许释放。
+
+| Type |
+| --------------------------------------------------------- |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => boolean` |
+
+---
+
+### `onStartShouldSetResponderCapture`
+
+如果父级`View`希望阻止子级`View`在触摸开始时成为响应者,则应该具有此处理程序,它返回`true`。
+
+| Type |
+| --------------------------------------------------------- |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => boolean` |
+
+---
+
+### `onTextLayout`
+
+在文本布局更改时调用。
+
+| Type |
+| ---------------------------------------------------- |
+| ([`TextLayoutEvent`](text#textlayoutevent)) => mixed |
+
+---
+
+### `pressRetentionOffset`
+
+当滚动视图被禁用时,这定义了您的触摸可以在按钮上移动多远,然后才会停用该按钮。一旦停用,请尝试将其移回,并且您会看到按钮再次被激活!在禁用滚动视图时来回移动它几次。确保传入一个常量以减少内存分配。
+
+| Type |
+| -------------------- |
+| [Rect](rect), number |
+
+---
+
+### `ref`
+
+一个 ref 设置器,在挂载时会被赋值一个[元素节点](element-nodes)。
+
+注意`Text`组件不提供文本节点,就像 Web 上的段落元素(``)是元素节点而不是文本节点一样。文本节点可以作为其子节点找到。
+
+---
+
+### `role`
+
+`role`向辅助技术的用户传达组件的用途。优先于[`accessibilityRole`](text#accessibilityrole)属性。
+
+| Type |
+| -------------------------- |
+| [Role](accessibility#role) |
+
+---
+
+### `selectable`
+
+决定用户是否可以选择文本,以使用原生的复制和粘贴功能。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `false` |
+
+---
+
+### `selectionColor`
Android
+
+文本的高亮颜色。
+
+| Type |
+| --------------- |
+| [color](colors) |
+
+---
+
+### `style`
+
+| Type |
+| -------------------------------------------------------------------- |
+| [Text Style](text-style-props), [View Style Props](view-style-props) |
+
+---
+
+### `suppressHighlighting` iOS
+
+设为`true`时,当文本被按下会没有任何视觉效果。默认情况下,文本被按下时会有一个灰色的、椭圆形的高光。
+
+| Type | Default |
+| ------- | ------- |
+| boolean | `false` |
+
+---
+
+### `testID`
+
+用来在端到端测试中定位此视图。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `textBreakStrategy` Android
+
+在 Android API 级别 23 及以上,设置文本换行策略,可能的值有`simple`、`highQuality`、`balanced`。
+
+| Type | Default |
+| ----------------------------------------------- | ------------- |
+| enum(`'simple'`, `'highQuality'`, `'balanced'`) | `highQuality` |
+
+---
+
+### `lineBreakStrategyIOS` iOS
+
+在 iOS 14+上设置换行策略。可能的值有`none`、`standard`、`hangul-word`和`push-out`。
+
+| Type | Default |
+| ----------------------------------------------------------- | -------- |
+| enum(`'none'`, `'standard'`, `'hangul-word'`, `'push-out'`) | `'none'` |
+
+## 类型定义
+
+### TextLayout
+
+`TextLayout` 对象是 [`TextLayoutEvent`](text#textlayoutevent) 回调的一部分,包含了 `Text` 行的测量数据。
+
+#### 示例
+
+```js
+{
+ capHeight: 10.496,
+ ascender: 14.624,
+ descender: 4,
+ width: 28.224,
+ height: 18.624,
+ xHeight: 6.048,
+ x: 0,
+ y: 0
+}
+```
+
+#### 属性
+
+| Name | Type | Optional | Description |
+| --------- | ------ | -------- | -------------------------------------- |
+| ascender | number | No | 文本布局变化后的行上升高度。 |
+| capHeight | number | No | 大写字母基线以上的部分的高度。 |
+| descender | number | No | 文本布局变化后的行下降高度。 |
+| height | number | No | 文本布局变化后的行高。 |
+| width | number | No | 文本布局变化后的线条宽度。 |
+| x | number | No | 线条在 Text 组件内的 X 坐标。 |
+| xHeight | number | No | 基线与中线之间的距离(小写字母大小)。 |
+| y | number | No | 线条在 Text 组件内的 Y 坐标。 |
+
+### TextLayoutEvent
+
+`TextLayoutEvent` 对象作为组件布局变化的结果在回调中返回。它包含一个名为 `lines` 的键,其值是一个数组,包含了对应于每一行渲染文本的 [`TextLayout`](text#textlayout) 对象。
+
+#### 示例
+
+```js
+{
+ lines: [
+ TextLayout,
+ TextLayout,
+ // ...
+ ];
+ target: 1127;
+}
+```
+
+#### 属性
+
+| Name | Type | Optional | Description |
+| ------ | --------------------------------------- | -------- | ---------------------------------- |
+| lines | array of [TextLayout](text#textlayout)s | No | 提供了每行渲染的 TextLayout 数据。 |
+| target | number | No | 元素的节点 ID。 |
diff --git a/cnwebsite/versioned_docs/version-0.85/textinput.md b/cnwebsite/versioned_docs/version-0.85/textinput.md
new file mode 100644
index 00000000000..84d6eff47bf
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/textinput.md
@@ -0,0 +1,1141 @@
+---
+id: textinput
+title: TextInput
+---
+
+TextInput 是一个允许用户在应用中通过键盘输入文本的基础组件。通过不同的属性,你可以配置自动更正、自动大小写、占位文字,以及数字键盘等不同键盘类型。
+
+最简单的用法就是放一个 `TextInput` 在界面上,然后订阅它的 `onChangeText` 事件来读取用户的输入。通常做法是在 `onChangeText` 中用 `setState`(或 `useState`)把用户的输入写入 state,然后在需要的地方从 state 中取值。它还有一些其它的事件,例如 `onSubmitEditing` 和 `onFocus`。一个简单的例子如下:
+
+```SnackPlayer name=TextInput%20Example
+import React from 'react';
+import {StyleSheet, TextInput} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const TextInputExample = () => {
+ const [text, onChangeText] = React.useState('Useless Text');
+ const [number, onChangeNumber] = React.useState('');
+
+ return (
+
+
+
+
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ input: {
+ height: 40,
+ margin: 12,
+ borderWidth: 1,
+ padding: 10,
+ },
+});
+
+export default TextInputExample;
+```
+
+原生元素还暴露了两个方法:`.focus()` 和 `.blur()`,可以让你在代码中主动让 TextInput 获取或失去焦点。
+
+注意有些属性仅在 `multiline` 为 `true/false` 时才有效。此外,当 `multiline=true` 时,为元素的某一个边添加边框样式(例如:`borderBottomColor`、`borderLeftWidth` 等)将不会生效。为了实现同样的效果,你可以使用一个 `View` 来包裹 `TextInput`:
+
+```SnackPlayer name=Multiline%20TextInput%20Example
+import React from 'react';
+import {TextInput, StyleSheet} from 'react-native';
+import {SafeAreaView, SafeAreaProvider} from 'react-native-safe-area-context';
+
+const MultilineTextInputExample = () => {
+ const [value, onChangeText] = React.useState('Useless Multiline Placeholder');
+
+ // 你可以试着输入一种颜色,比如red,那么这个red就会作用到View的背景色样式上
+ return (
+
+
+ onChangeText(text)}
+ value={value}
+ style={styles.textInput}
+ />
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ textInput: {
+ padding: 10,
+ borderColor: '#000',
+ borderWidth: 1,
+ margin: 12,
+ },
+});
+
+export default MultilineTextInputExample;
+```
+
+`TextInput` 在视图底部默认会有一条下划线边框。这个边框的 padding 是由系统提供的背景图片决定的,无法直接修改。要避免这个问题,可以不显式设置高度,让系统自己把边框画在合适的位置;或者将 `underlineColorAndroid` 设为透明来隐藏这条下划线。
+
+注意,在 Android 上对输入框进行文本选择时,可能会把当前 Activity 的 `windowSoftInputMode` 参数改成 `adjustResize`。这会在键盘弹出时影响使用 `position: 'absolute'` 布局的组件。要避免这种行为,可以在 AndroidManifest.xml 里显式设置合适的 `windowSoftInputMode`(详见 https://developer.android.com/guide/topics/manifest/activity-element.html),或者通过原生代码在运行时控制这个参数。
+
+---
+
+# Reference
+
+## Props
+
+### [View Props](view.md#props)
+
+继承 [View Props](view.md#props)。
+
+---
+
+### `allowFontScaling`
+
+控制字体是否要根据系统的“字体大小”辅助选项来进行缩放。默认值为`true`。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `autoCapitalize`
+
+控制 TextInput 是否要自动将特定字符切换为大写。某些键盘类型(例如 `name-phone-pad`)不支持此特性。
+
+- `characters`: 所有的字符。
+- `words`: 每个单词的第一个字符。
+- `sentences`: 每句话的第一个字符(默认)。
+- `none`: 不切换。
+
+| Type |
+| ------------------------------------------------ |
+| enum('none', 'sentences', 'words', 'characters') |
+
+---
+
+### `autoComplete`
+
+为系统提供自动补全提示,从而启用系统级的自动填充。在 Android 上,系统会通过启发式判断内容类型,尽可能提供自动填充。要禁用自动补全,将 `autoComplete` 设为 `off`。
+
+The following values work across platforms:
+
+- `additional-name`
+- `address-line1`
+- `address-line2`
+- `birthdate-day` (iOS 17+)
+- `birthdate-full` (iOS 17+)
+- `birthdate-month` (iOS 17+)
+- `birthdate-year` (iOS 17+)
+- `cc-csc` (iOS 17+)
+- `cc-exp` (iOS 17+)
+- `cc-exp-day` (iOS 17+)
+- `cc-exp-month` (iOS 17+)
+- `cc-exp-year` (iOS 17+)
+- `cc-number`
+- `country`
+- `current-password`
+- `email`
+- `family-name`
+- `given-name`
+- `honorific-prefix`
+- `honorific-suffix`
+- `name`
+- `new-password`
+- `off`
+- `one-time-code`
+- `postal-code`
+- `street-address`
+- `tel`
+- `username`
+
+iOS
+
+下列取值仅在 iOS 上生效:
+
+- `cc-family-name` (iOS 17+)
+- `cc-given-name` (iOS 17+)
+- `cc-middle-name` (iOS 17+)
+- `cc-name` (iOS 17+)
+- `cc-type` (iOS 17+)
+- `nickname`
+- `organization`
+- `organization-title`
+- `url`
+
+Android
+
+下列取值仅在 Android 上生效:
+
+- `gender`
+- `name-family`
+- `name-given`
+- `name-middle`
+- `name-middle-initial`
+- `name-prefix`
+- `name-suffix`
+- `password`
+- `password-new`
+- `postal-address`
+- `postal-address-country`
+- `postal-address-extended`
+- `postal-address-extended-postal-code`
+- `postal-address-locality`
+- `postal-address-region`
+- `sms-otp`
+- `tel-country-code`
+- `tel-device`
+- `tel-national`
+- `username-new`
+
+| Type |
+| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| enum('additional-name', 'address-line1', 'address-line2', 'birthdate-day', 'birthdate-full', 'birthdate-month', 'birthdate-year', 'cc-csc', 'cc-exp', 'cc-exp-day', 'cc-exp-month', 'cc-exp-year', 'cc-number', 'country', 'current-password', 'email', 'family-name', 'given-name', 'honorific-prefix', 'honorific-suffix', 'name', 'new-password', 'off', 'one-time-code', 'postal-code', 'street-address', 'tel', 'username', 'cc-family-name', 'cc-given-name', 'cc-middle-name', 'cc-name', 'cc-type', 'nickname', 'organization', 'organization-title', 'url', 'gender', 'name-family', 'name-given', 'name-middle', 'name-middle-initial', 'name-prefix', 'name-suffix', 'password', 'password-new', 'postal-address', 'postal-address-country', 'postal-address-extended', 'postal-address-extended-postal-code', 'postal-address-locality', 'postal-address-region', 'sms-otp', 'tel-country-code', 'tel-device', 'tel-national', 'username-new') |
+
+---
+
+### `autoCorrect`
+
+如果为 false,会关闭拼写自动修正。默认值是 true。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `autoFocus`
+
+如果为 true,在`componentDidMount`后会获得焦点。默认值为 false。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### 🗑️ `blurOnSubmit`
+
+:::warning Deprecated
+`submitBehavior` 现在取代了 `blurOnSubmit`,并会覆盖由 `blurOnSubmit` 定义的行为。详见 [submitBehavior](textinput#submitbehavior)。
+:::
+
+如果为 `true`,文本框会在提交的时候失焦。对于单行输入框默认值为 `true`,多行则为 `false`。注意:对于多行输入框来说,如果将 `blurOnSubmit` 设为 `true`,按下回车键时会失去焦点并触发 `onSubmitEditing` 事件,而不会在输入框中插入换行。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `caretHidden`
+
+如果为 true,则隐藏光标。默认值为 false。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `clearButtonMode` iOS
+
+是否要在文本框右侧显示“清除”按钮。仅在单行模式下可用。默认值为`never`。
+
+| Type |
+| ---------------------------------------------------------- |
+| enum('never', 'while-editing', 'unless-editing', 'always') |
+
+---
+
+### `clearTextOnFocus` iOS
+
+如果为 true,每次开始输入的时候都会清除文本框的内容。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `contextMenuHidden`
+
+如果为 `true`,将隐藏文本选择时弹出的上下文菜单。默认值为 `false`。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `dataDetectorTypes` iOS
+
+设置 text input 内能被转化为可点击 URL 的数据的类型。当且仅当`multiline={true}`和`editable={false}`时起作用。默认情况下不检测任何数据类型。
+
+可接受一个类型值或类型值数组。
+
+`dataDetectorTypes`的可用值有:
+
+- `'phoneNumber'`
+- `'link'`
+- `'address'`
+- `'calendarEvent'`
+- `'none'`
+- `'all'`
+
+| Type |
+| -------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| enum('phoneNumber', 'link', 'address', 'calendarEvent', 'none', 'all'), ,array of enum('phoneNumber', 'link', 'address', 'calendarEvent', 'none', 'all') |
+
+---
+
+### `defaultValue`
+
+提供一个文本框中的初始值。当用户开始输入的时候,值就可以改变。在一些简单的使用情形下,如果你不想用监听消息然后更新 value 属性的方法来保持属性和状态同步的时候,就可以用 defaultValue 来代替。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `disableKeyboardShortcuts` iOS
+
+如果为 `true`,将禁用键盘上的快捷按钮(撤销/重做和复制按钮)。默认值为 `false`。
+
+| Type | Default |
+| ---- | ------- |
+| bool | `false` |
+
+---
+
+### `cursorColor` Android
+
+如果设置,将改变组件中光标(caret)的颜色。与 `selectionColor` 不同,光标颜色会独立于选区高亮颜色单独设置。
+
+| Type |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `disableFullscreenUI` Android
+
+当值为 false 时, 如果 text input 的周围有少量可用空间的话(比如说,当手机横过来时),操作系统可能会将这个 text input 设置为全屏模式。当值为 true 时, 这个特性不可用,text input 就是普通的模式。默认为 false。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `editable`
+
+如果为 false,文本框是不可编辑的。默认值为 true。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `enablesReturnKeyAutomatically` iOS
+
+如果为 `true`,当输入框内容为空时,键盘会禁用回车键;一旦有文本输入,则自动启用回车键。默认值为 `false`。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `enterKeyHint`
+
+决定“回车”键上显示的文字。优先级高于 `returnKeyType` 属性。
+
+以下取值在所有平台上都可用:
+
+- `done`
+- `next`
+- `search`
+- `send`
+- `go`
+
+_仅 Android 可用_
+
+以下取值仅在 Android 上生效:
+
+- `previous`
+
+_仅 iOS 可用_
+
+以下取值仅在 iOS 上生效:
+
+- `enter`
+
+| Type |
+| ----------------------------------------------------------------- |
+| enum('enter', 'done', 'next', 'previous', 'search', 'send', 'go') |
+
+---
+
+### `importantForAutofill` Android
+
+告知操作系统:应用中的某个输入字段是否应该被包含在用于自动填充(autofill)的视图结构中(Android API 26+)。可选值有 `auto`、`no`、`noExcludeDescendants`、`yes` 和 `yesExcludeDescendants`,默认值为 `auto`。
+
+- `auto`:让 Android 系统自行通过启发式判断该视图是否对自动填充重要。
+- `no`:此视图对自动填充不重要。
+- `noExcludeDescendants`:此视图及其所有子视图对自动填充都不重要。
+- `yes`:此视图对自动填充很重要。
+- `yesExcludeDescendants`:此视图对自动填充重要,但其子视图不重要。
+
+| Type |
+| -------------------------------------------------------------------------- |
+| enum('auto', 'no', 'noExcludeDescendants', 'yes', 'yesExcludeDescendants') |
+
+---
+
+### `inlineImageLeft` Android
+
+指定一个图片放置在左侧。图片必须放置在`/android/app/src/main/res/drawable`目录下,经过编译后按如下形式引用(无路径无后缀):
+
+```
+
+```
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `inlineImagePadding` Android
+
+若有内联图片,设置图片与文本输入框之间的内边距。
+
+| Type |
+| ------ |
+| number |
+
+---
+
+### `inputAccessoryViewID` iOS
+
+一个可选的标识符,用来将自定义的 [InputAccessoryView](inputaccessoryview.md) 绑定到当前输入框。当该输入框获得焦点时,这个 InputAccessoryView 会显示在键盘上方。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `inputAccessoryViewButtonLabel` iOS
+
+可选的按钮文案,用来覆盖默认 [InputAccessoryView](inputaccessoryview.md) 上的按钮标签。
+
+默认情况下,这个按钮标签不会做本地化处理,可以通过此属性提供一份本地化后的文案。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `inputMode`
+
+行为类似 HTML 中的 `inputmode` 属性,用来决定打开哪种键盘(如 `numeric`),并且优先级高于 `keyboardType`。
+
+支持以下取值:
+
+- `none`
+- `text`
+- `decimal`
+- `numeric`
+- `tel`
+- `search`
+- `email`
+- `url`
+
+| Type |
+| --------------------------------------------------------------------------- |
+| enum('decimal', 'email', 'none', 'numeric', 'search', 'tel', 'text', 'url') |
+
+---
+
+### `keyboardAppearance` iOS
+
+设置键盘的配色风格。
+
+| Type |
+| -------------------------------- |
+| enum('default', 'light', 'dark') |
+
+---
+
+### `keyboardType`
+
+决定弹出何种软键盘类型,譬如`numeric`(纯数字键盘)。
+
+所有键盘类型的示意图可参考这里:[链接](https://davidl.fr/blog/keyboard-react-native-ios-android#all-react-native-keyboard-type-examples-i-os-on-the-left-android-on-the-right)。
+
+这些值在所有平台都可用:
+
+- `default`
+- `number-pad`
+- `decimal-pad`
+- `numeric`
+- `email-address`
+- `phone-pad`
+- `url`
+
+_iOS Only_
+
+下面的值仅 iOS 可用:
+
+- `ascii-capable`
+- `numbers-and-punctuation`
+- `name-phone-pad`
+- `twitter`
+- `web-search`
+
+_Android Only_
+
+下面的值仅 Android 可用:
+
+- `visible-password`
+
+| Type |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| enum('default', 'email-address', 'numeric', 'phone-pad', 'ascii-capable', 'numbers-and-punctuation', 'url', 'number-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search', 'visible-password') |
+
+---
+
+### `lineBreakStrategyIOS` iOS
+
+在 iOS 14+ 上设置换行策略。可选值有 `none`、`standard`、`hangul-word` 和 `push-out`。
+
+| Type | Default |
+| ----------------------------------------------------------- | -------- |
+| enum(`'none'`, `'standard'`, `'hangul-word'`, `'push-out'`) | `'none'` |
+
+---
+
+### `lineBreakModeIOS` iOS
+
+在 iOS 上设置换行模式。可选值有:`wordWrapping`、`char`、`clip`、`head`、`middle` 和 `tail`。
+
+| Type | Default |
+| -------------------------------------------------------------------------- | ---------------- |
+| enum(`'wordWrapping'`, `'char'`, `'clip'`, `'head'`, `'middle'`, `'tail'`) | `'wordWrapping'` |
+
+---
+
+### `maxFontSizeMultiplier`
+
+指定在启用 `allowFontScaling` 时字体可放大的最大倍数。可选取值:
+
+- `null/undefined`(默认):继承父节点或全局默认值(0)
+- `0`:不限制最大值,忽略父级/全局默认
+- `>= 1`:将当前节点的 `maxFontSizeMultiplier` 设置为该数值
+
+| Type |
+| ------ |
+| number |
+
+---
+
+### `maxLength`
+
+限制文本框中最多的字符数。使用这个属性而不用 JS 逻辑去实现,可以避免闪烁的现象。
+
+| Type |
+| ------ |
+| number |
+
+---
+
+### `multiline`
+
+如果为 true,文本框中可以输入多行文字。默认值为 false。
+
+:::note
+需要注意的是,此属性在 iOS 上会使文字顶部对齐,而在 Android 上会使文字垂直居中。如需在两个平台上保持一致的行为,可配合 `textAlignVertical` 设为 `top`。
+:::
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `numberOfLines`
+
+:::note
+`numberOfLines` 在 iOS 上仅在[新架构](/architecture/landing-page)中可用。
+:::
+
+设置 `TextInput` 的最大行数。通常配合 `multiline={true}` 一起使用,以便填满指定的行数。
+
+| Type |
+| ------ |
+| number |
+
+---
+
+### `onBlur`
+
+当文本框失去焦点的时候调用此回调函数。
+
+:::note
+如果你尝试从 `nativeEvent` 中读取 `text`,要注意该值可能为 `undefined`,从而导致一些意料之外的错误。如果你需要拿到 TextInput 的最终值,更推荐使用在编辑完成时触发的 [`onEndEditing`](textinput#onendediting) 事件。
+:::
+
+| Type |
+| -------------------------------------------------------- |
+| `md ({nativeEvent: [TargetEvent](targetevent)}) => void` |
+
+---
+
+### `onChange`
+
+当文本框内容变化时调用此回调函数。回调参数为`{ nativeEvent: { eventCount, target, text} }`。
+
+| Type |
+| ----------------------------------------------------- |
+| (`{nativeEvent: {eventCount, target, text}}`) => void |
+
+---
+
+### `onChangeText`
+
+当文本框内容变化时调用此回调函数。改变后的文字内容会作为参数传递。
+
+| Type |
+| -------- |
+| function |
+
+---
+
+### `onContentSizeChange`
+
+当文本输入内容的尺寸发生变化时调用。仅在多行输入框上触发。
+
+| Type |
+| ---------------------------------------------------------- |
+| (`{nativeEvent: {contentSize: {width, height} }}`) => void |
+
+---
+
+### `onEndEditing`
+
+当文本输入结束后调用此回调函数。
+
+| Type |
+| -------- |
+| function |
+
+---
+
+### `onPressIn`
+
+当按压开始时调用的回调。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onPressOut`
+
+当按压结束(手指抬起)时调用的回调。
+
+| Type |
+| ------------------------------------------------------ |
+| `md ({nativeEvent: [PressEvent](pressevent)}) => void` |
+
+---
+
+### `onFocus`
+
+当文本框获得焦点的时候调用此回调函数。
+
+| Type |
+| -------------------------------------------------------- |
+| `md ({nativeEvent: [TargetEvent](targetevent)}) => void` |
+
+---
+
+### `onKeyPress`
+
+当一个键被按下的时候调用此回调。传递给回调函数的参数为`{ nativeEvent: { key: keyValue } }`,其中`keyValue`即为被按下的键。会在 onChange 之前调用。注意:在 Android 上只有软键盘会触发此事件,物理键盘不会触发。
+
+| Type |
+| ------------------------------------------- |
+| (`{nativeEvent: {key: keyValue} }`) => void |
+
+---
+
+### `onLayout`
+
+当组件加载或者布局变化的时候调用。
+
+| Type |
+| -------------------------------------------------------- |
+| `md ({nativeEvent: [LayoutEvent](layoutevent)}) => void` |
+
+---
+
+### `onScroll`
+
+在内容滚动时持续调用,传回参数的格式形如`{ nativeEvent: { contentOffset: { x, y } } }`。也可能包含其他和滚动事件相关的参数,但是在 Android 上,出于性能考虑,不会提供`contentSize`参数。
+
+| Type |
+| --------------------------------------------------- |
+| (`{nativeEvent: {contentOffset: {x, y} }}`) => void |
+
+---
+
+### `onSelectionChange`
+
+光标位置变化时,传回参数的格式形如`{ nativeEvent: { selection: { start, end } } }`。
+
+| Type |
+| ----------------------------------------------------- |
+| (`{nativeEvent: {selection: {start, end} }}`) => void |
+
+---
+
+### `onSubmitEditing`
+
+此回调函数当软键盘的`确定`/`提交`按钮被按下的时候调用此函数,所传参数为`{nativeEvent: {text, eventCount, target}}`。
+
+| Type |
+| ----------------------------------------------------- |
+| (`{nativeEvent: {text, eventCount, target}}`) => void |
+
+Note that on iOS this method isn't called when using `keyboardType="phone-pad"`.
+
+---
+
+### `placeholder`
+
+在尚未输入任何文字之前显示的占位字符串。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `placeholderTextColor`
+
+占位字符串的文字颜色。
+
+| Type |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `readOnly`
+
+如果为 `true`,则文本不可编辑。默认值为 `false`。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `returnKeyLabel` Android
+
+设置“回车”键上显示的文字。优先级高于 `returnKeyType`。
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `returnKeyType`
+
+决定“确定”按钮显示的内容。在 Android 上你还可以使用`returnKeyLabel`。
+
+_Cross platform_
+
+下列这些选项是跨平台可用的:
+
+- `done`
+- `go`
+- `next`
+- `search`
+- `send`
+
+_Android Only_
+
+下列这些选项仅 Android 可用:
+
+- `none`
+- `previous`
+
+_iOS Only_
+
+下列这些选项仅 iOS 可用:
+
+- `default`
+- `emergency-call`
+- `google`
+- `join`
+- `route`
+- `yahoo`
+
+| Type |
+| --------------------------------------------------------------------------------------------------------------------------------- |
+| enum('done', 'go', 'next', 'search', 'send', 'none', 'previous', 'default', 'emergency-call', 'google', 'join', 'route', 'yahoo') |
+
+### `rejectResponderTermination` iOS
+
+如果为 `true`,允许 TextInput 将触摸事件传递给父组件。这样像 SwipeableListView 这样的组件就可以在 iOS 上从 TextInput 开始滑动(Android 默认就是这种行为)。如果为 `false`,则 TextInput 会始终请求自己处理输入事件(除非被禁用)。默认值为 `true`。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `rows` Android
+
+设置 `TextInput` 的行数。通常配合 `multiline={true}` 一起使用,以便填满对应的行数。
+
+| Type |
+| ------ |
+| number |
+
+---
+
+### `scrollEnabled` iOS
+
+如果为 `false`,将禁用文本视图的滚动。默认值为 `true`。仅在 `multiline={true}` 时生效。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `secureTextEntry`
+
+如果为 true,文本框会遮住之前输入的文字,这样类似密码之类的敏感文字可以更加安全。默认值为 false。`multiline={true}`时不可用。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `selection`
+
+设置选中文字的范围(指定首尾的索引值)。如果首尾为同一索引位置,则相当于指定光标的位置。
+
+| Type |
+| ------------------------------------- |
+| object: `{start: number,end: number}` |
+
+---
+
+### `selectionColor`
+
+设置输入框高亮时的颜色(还包括光标)。
+
+| Type |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `selectionHandleColor` Android
+
+设置选择句柄(光标两端拖拽小圆点)的颜色。与 `selectionColor` 不同,它允许单独定制选择句柄的颜色,而不影响选区高亮的颜色。
+
+| Type |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `selectTextOnFocus`
+
+如果为 true,当获得焦点的时候,所有的文字都会被选中。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `showSoftInputOnFocus`
+
+当为 `false` 时,在输入框获得焦点时将阻止软键盘弹出。默认值为 `true`。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `smartInsertDelete` iOS
+
+如果为 `false`,iOS 系统在粘贴操作后不会自动插入额外空格,在剪切或删除操作后也不会自动删除一个或两个空格。
+
+| Type | Default |
+| ---- | ------- |
+| bool | `true` |
+
+---
+
+### `spellCheck` iOS
+
+如果设置为`false`,则禁用拼写检查的样式(比如错误拼写的单词下的红线)。默认值继承自`autoCorrect`。
+
+| Type |
+| ---- |
+| bool |
+
+---
+
+### `submitBehavior`
+
+当回车键按下时,
+
+对于单行输入框:
+
+- `'newline'` 默认等同于 `'blurAndSubmit'`
+- `undefined` 默认等同于 `'blurAndSubmit'`
+
+对于多行输入框:
+
+- `'newline'` 会插入一个新行
+- `undefined` 默认等同于 `'newline'`
+
+对于单行和多行输入框:
+
+- `'submit'` 只发送提交事件,不使输入框失焦
+- `'blurAndSubmit`' 会使输入框失焦并发送提交事件
+
+| Type |
+| ------------------------------------------ |
+| enum('submit', 'blurAndSubmit', 'newline') |
+
+---
+
+### `textAlign`
+
+控制输入文字在输入框中的对齐方式,可选值为左对齐、居中或右对齐:
+
+- `left`
+- `center`
+- `right`
+
+| Type |
+| ------------------------------- |
+| enum('left', 'center', 'right') |
+
+---
+
+### `textContentType` iOS
+
+向键盘和系统提供用户输入内容的语义信息,让系统更好地理解该字段的用途。
+
+:::note
+[`autoComplete`](#autocomplete) 提供了相同的能力,并且适用于所有平台。你可以结合 [`Platform.select`](/docs/next/platform#select) 来实现不同平台上的差异化行为。
+
+建议避免同时使用 `textContentType` 和 `autoComplete`。出于向后兼容考虑,当两者都设置时,以 `textContentType` 为准。
+:::
+
+你可以将 `textContentType` 设置为 `username` 或 `password` 来启用从设备钥匙串自动填充登录信息。
+
+`newPassword` 可用于标记一个“新密码”输入框,方便用户将其保存在钥匙串中;`oneTimeCode` 可用于标记验证码输入框,以便从短信中自动填充一次性验证码。
+
+若要禁用自动填充,将 `textContentType` 设为 `none`。
+
+Possible values for `textContentType` are:
+
+- `none`
+- `addressCity`
+- `addressCityAndState`
+- `addressState`
+- `birthdate` (iOS 17+)
+- `birthdateDay` (iOS 17+)
+- `birthdateMonth` (iOS 17+)
+- `birthdateYear` (iOS 17+)
+- `countryName`
+- `creditCardExpiration` (iOS 17+)
+- `creditCardExpirationMonth` (iOS 17+)
+- `creditCardExpirationYear` (iOS 17+)
+- `creditCardFamilyName` (iOS 17+)
+- `creditCardGivenName` (iOS 17+)
+- `creditCardMiddleName` (iOS 17+)
+- `creditCardName` (iOS 17+)
+- `creditCardNumber`
+- `creditCardSecurityCode` (iOS 17+)
+- `creditCardType` (iOS 17+)
+- `emailAddress`
+- `familyName`
+- `fullStreetAddress`
+- `givenName`
+- `jobTitle`
+- `location`
+- `middleName`
+- `name`
+- `namePrefix`
+- `nameSuffix`
+- `newPassword`
+- `nickname`
+- `oneTimeCode`
+- `organizationName`
+- `password`
+- `postalCode`
+- `streetAddressLine1`
+- `streetAddressLine2`
+- `sublocality`
+- `telephoneNumber`
+- `URL`
+- `username`
+
+| Type |
+| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| enum('none', 'addressCity', 'addressCityAndState', 'addressState', 'birthdate', 'birthdateDay', 'birthdateMonth', 'birthdateYear', 'countryName', 'creditCardExpiration', 'creditCardExpirationMonth', 'creditCardExpirationYear', 'creditCardFamilyName', 'creditCardGivenName', 'creditCardMiddleName', 'creditCardName', 'creditCardNumber', 'creditCardSecurityCode', 'creditCardType', 'emailAddress', 'familyName', 'fullStreetAddress', 'givenName', 'jobTitle', 'location', 'middleName', 'name', 'namePrefix', 'nameSuffix', 'newPassword', 'nickname', 'oneTimeCode', 'organizationName', 'password', 'postalCode', 'streetAddressLine1', 'streetAddressLine2', 'sublocality', 'telephoneNumber', 'URL', 'username') |
+
+---
+
+### `passwordRules` iOS
+
+当在 iOS 上将 `textContentType` 设置为 `newPassword` 时,可以告诉系统密码的最小要求,以便系统为你生成一个满足条件的密码。如何编写合法的 `PasswordRules` 字符串,请参考 [Apple 文档](https://developer.apple.com/password-rules/)。
+
+:::tip
+如果没有看到系统弹出的密码生成对话框,请检查:
+
+- 是否开启了自动填充:**设置** → **密码与账户** → 打开 **自动填充密码**;
+- 是否启用了 iCloud 钥匙串:**设置** → **Apple ID** → **iCloud** → **钥匙串** → 打开 **iCloud 钥匙串**。
+ :::
+
+| Type |
+| ------ |
+| string |
+
+---
+
+### `style`
+
+注意:并不是所有 Text 相关样式都对 `TextInput` 有效,下面是不完全的“不支持列表”:
+
+- `borderLeftWidth`
+- `borderTopWidth`
+- `borderRightWidth`
+- `borderBottomWidth`
+- `borderTopLeftRadius`
+- `borderTopRightRadius`
+- `borderBottomRightRadius`
+- `borderBottomLeftRadius`
+
+[Styles](style.md)
+
+| Type |
+| --------------------- |
+| [Text](text.md#style) |
+
+---
+
+### `textBreakStrategy` Android
+
+在 Android API Level 23+ 上设置文本换行策略,可选值有 `simple`、`highQuality`、`balanced`,默认值为 `highQuality`。
+
+| Type |
+| ----------------------------------------- |
+| enum('simple', 'highQuality', 'balanced') |
+
+---
+
+### `underlineColorAndroid` Android
+
+`TextInput` 下划线的颜色。
+
+| Type |
+| ------------------ |
+| [color](colors.md) |
+
+---
+
+### `value`
+
+要在输入框中显示的值。`TextInput` 是一个受控组件,这意味着如果提供了 `value`,原生输入框的内容会被强制与该值保持一致。大多数情况下这都很好用,但在某些场景下可能会导致闪烁——常见原因是通过保持 `value` 不变来阻止用户编辑。除了维持同样的 `value` 之外,更好的做法是将 `editable` 设为 `false`,或者设置/更新 `maxLength` 来避免不希望的编辑,同时不产生闪烁。
+
+| Type |
+| ------ |
+| string |
+
+## Methods
+
+### `.focus()`
+
+```tsx
+focus();
+```
+
+使原生输入框请求获得焦点。
+
+### `.blur()`
+
+```tsx
+blur();
+```
+
+使原生输入框失去焦点。
+
+### `clear()`
+
+```tsx
+clear();
+```
+
+清空 `TextInput` 中的所有文本。
+
+---
+
+### `isFocused()`
+
+```tsx
+isFocused(): boolean;
+```
+
+如果当前输入框处于焦点状态,则返回 `true`,否则返回 `false`。
+
+# Known issues
+
+- [react-native#19096](https://github.com/facebook/react-native/issues/19096):不支持 Android 的 `onKeyPreIme`。
+- [react-native#19366](https://github.com/facebook/react-native/issues/19366):在通过返回键关闭 Android 键盘之后调用 `.focus()` 无法再次唤起键盘。
+- [react-native#26799](https://github.com/facebook/react-native/issues/26799):在 `keyboardType="email-address"` 或 `keyboardType="phone-pad"` 时,不支持 Android 上的 `secureTextEntry`。
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/_markdown_native_deprecation.mdx b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/_markdown_native_deprecation.mdx
new file mode 100644
index 00000000000..97794c10904
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/_markdown_native_deprecation.mdx
@@ -0,0 +1,4 @@
+:::info
+原生模块(Native Module)和原生组件(Native Components)是我们在旧架构中使用的稳定技术。
+当新架构稳定后,它们将在未来被弃用。新架构使用 [Turbo Native Module](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/turbo-modules.md) 和 [Fabric Native Components](https://github.com/reactwg/react-native-new-architecture/blob/main/docs/fabric-native-components.md) 来实现类似的效果。
+:::
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/advanced-topics-components.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/advanced-topics-components.md
new file mode 100644
index 00000000000..8c2140137c8
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/advanced-topics-components.md
@@ -0,0 +1,9 @@
+# Fabric 组件开发高级主题
+
+本文档包含一组高级主题,用于实现 Fabric 组件的更复杂功能。建议先阅读 [Codegen](/docs/the-new-architecture/what-is-codegen) 部分和 [Fabric 组件](/docs/fabric-native-components-introduction)指南。
+
+本指南将涵盖以下主题:
+
+- [向您的组件添加原生命令](/docs/the-new-architecture/fabric-component-native-commands)
+- [直接操作](/docs/the-new-architecture/direct-manipulation)
+- [测量布局](/docs/the-new-architecture/layout-measurements)
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/advanced-topics-modules.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/advanced-topics-modules.md
new file mode 100644
index 00000000000..bf21d0593ca
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/advanced-topics-modules.md
@@ -0,0 +1,10 @@
+# 原生模块开发高级主题
+
+本文档包含一组高级主题,用于实现原生模块的更复杂功能。建议先阅读 [Codegen](/docs/the-new-architecture/what-is-codegen) 部分和[原生模块](/docs/turbo-native-modules-introduction)指南。
+
+本指南将涵盖以下主题:
+
+- [向您的 C++ 模块添加自定义 C++ 类型](/docs/the-new-architecture/custom-cxx-types)
+- [在您的模块中使用 Swift](/docs/next/the-new-architecture/turbo-modules-with-swift)
+- [从您的原生模块发出自定义事件](/docs/next/the-new-architecture/native-modules-custom-events)
+- [原生模块生命周期](/docs/next/the-new-architecture/native-modules-lifecycle)
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/codegen-cli.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/codegen-cli.md
new file mode 100644
index 00000000000..88fc76a4eee
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/codegen-cli.md
@@ -0,0 +1,69 @@
+# Codegen CLI
+
+调用 Gradle 或手动调用脚本可能很难记住,并且需要大量的仪式。
+
+为了简化它,我们创建了一个可以帮助您运行这些任务的 CLI 工具:**Codegen** cli。此命令为您的项目运行 [@react-native/codegen](https://www.npmjs.com/package/@react-native/codegen)。可用选项如下:
+
+```sh
+npx @react-native-community/cli codegen --help
+Usage: rnc-cli codegen [options]
+
+Options:
+ --verbose Increase logging verbosity
+ --path Path to the React Native project root. (default: "/Users/MyUsername/projects/my-app")
+ --platform Target platform. Supported values: "android", "ios", "all". (default: "all")
+ --outputPath Path where generated artifacts will be output to.
+ -h, --help display help for command
+```
+
+## 示例
+
+- 从当前工作目录读取 `package.json`,根据其 codegenConfig 生成代码。
+
+```shell
+npx @react-native-community/cli codegen
+```
+
+- 从当前工作目录读取 `package.json`,在 codegenConfig 中定义的位置生成 iOS 代码。
+
+```shell
+npx @react-native-community/cli codegen --platform ios
+```
+
+- 从 `third-party/some-library` 读取 `package.json`,在 `third-party/some-library/android/generated` 中生成 Android 代码。
+
+```shell
+npx @react-native-community/cli codegen \
+ --path third-party/some-library \
+ --platform android \
+ --outputPath third-party/some-library/android/generated
+```
+
+## 将生成的代码包含到库中
+
+Codegen CLI 是库开发者的绝佳工具。它可用于快速查看生成的代码,以了解您需要实现哪些接口。
+
+通常,生成的代码不包含在库中,使用该库的应用负责在构建时运行 Codegen。
+这对大多数情况都是一个很好的设置,但 Codegen 还提供了一种机制,通过 `includesGeneratedCode` 属性将生成的代码包含在库本身中。
+
+重要的是要了解使用 `includesGeneratedCode = true` 的含义。包含生成的代码有几个好处,例如:
+
+- 无需依赖应用为您运行 **Codegen**,生成的代码始终存在。
+- 实现文件始终与生成的接口一致(这使您的库代码对 codegen 中的 API 更改更具弹性)。
+- 无需包含两组文件以在 Android 上支持两种架构。您只能保留新架构,并且保证向后兼容。
+- 由于所有原生代码都在那里,因此可以将库的原生部分作为预构建版本发送。
+
+另一方面,您还需要注意一个缺点:
+
+- 生成的代码将使用库中定义的 React Native 版本。因此,如果您的库随 React Native 0.76 一起发布,则生成的代码将基于该版本。这可能意味着生成的代码与使用**之前** React Native 版本的应用不兼容(例如,运行在 React Native 0.75 上的应用)。
+
+## 启用 `includesGeneratedCode`
+
+要启用此设置:
+
+- 将 `includesGeneratedCode` 属性添加到库的 `package.json` 文件中的 `codegenConfig` 字段中。将其值设置为 `true`。
+- 使用 codegen CLI 在本地运行 **Codegen**。
+- 更新您的 `package.json` 以包含生成的代码。
+- 更新您的 `podspec` 以包含生成的代码。
+- 更新您的 `build.Gradle` 文件以包含生成的代码。
+- 在 `react-native.config.js` 中更新 `cmakeListsPath`,以便 Gradle 不在构建目录中查找 CMakeLists 文件,而是在您的 outputDir 中查找。
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/create-module-library.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/create-module-library.md
new file mode 100644
index 00000000000..4ec6071c5ad
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/create-module-library.md
@@ -0,0 +1,192 @@
+# 为您的模块创建库
+
+React Native 拥有丰富的库生态系统来解决常见问题。我们在 [reactnative.directory](https://reactnative.directory) 网站上收集 React Native 库,这是每个 React Native 开发者都值得收藏的绝佳资源。
+
+有时,您可能正在开发一个值得提取为单独库以便代码重用的模块。这可以是您想在所有应用中重用的库,您想作为开源组件分发到生态系统的库,甚至是您想出售的库。
+
+在本指南中,您将学习:
+
+- 如何将模块提取到库中
+- 如何使用 NPM 分发库
+
+## 将模块提取到库中
+
+您可以使用 [`create-react-native-library`](https://callstack.github.io/react-native-builder-bob/create) 工具创建新库。此工具设置了一个包含所有所需样板代码的新库:所有配置文件和各个平台所需的所有文件。它还带有一个不错的交互式菜单来指导您完成库的创建。
+
+要将模块提取到单独的库中,您可以按照以下步骤操作:
+
+1. 创建新库
+2. 将代码从应用移动到库
+3. 更新代码以反映新结构
+4. 发布它。
+
+### 1. 创建库
+
+1. 通过运行命令开始创建过程:
+
+```sh
+npx create-react-native-library@latest
+```
+
+2. 为您的模块添加名称。它必须是一个有效的 npm 名称,因此应该全部小写。您可以使用 `-` 来分隔单词。
+3. 为包添加描述。
+4. 继续填写表单,直到您到达问题 _"您想开发什么类型的库?"_
+ 
+5. 为了本指南的目的,选择 _Turbo module_ 选项。请注意,您可以为新架构和旧架构创建库。
+6. 然后,您可以选择是否想要一个访问平台的库(Kotlin 和 Objective-C)或共享的 C++ 库(Android 和 iOS 的 C++)。
+7. 最后,选择 `Test App` 作为最后一个选项。此选项创建的库中已在库文件夹内配置了一个单独的应用。
+
+一旦交互式提示完成,该工具会创建一个文件夹,其结构在 Visual Studio Code 中如下所示:
+
+
+
+随意探索为您创建的代码。但是,最重要的部分是:
+
+- `android` 文件夹:这是 Android 代码所在的位置
+- `cpp` 文件夹:这是 c++ 代码所在的位置
+- `ios` 文件夹:这是 iOS 代码所在的位置
+- `src` 文件夹:这是 JS 代码所在的位置。
+
+`package.json` 已经配置了我们提供给 `create-react-native-library` 工具的所有信息,包括包的名称和描述。请注意,`package.json` 也已经配置为运行 Codegen。
+
+```json
+ "codegenConfig": {
+ "name": "RNSpec",
+ "type": "all",
+ "jsSrcsDir": "src",
+ "outputDir": {
+ "ios": "ios/generated",
+ "android": "android/generated"
+ },
+ "android": {
+ "javaPackageName": "com."
+ }
+ },
+```
+
+最后,该库已经包含了让库与 iOS 和 Android 链接的所有基础设施。
+
+### 2. 从您的应用复制代码
+
+本指南的其余部分假设您的应用中有一个本地 Turbo Native Module,按照网站中其他指南所示的指南创建:平台特定的 Turbo Native Modules,或[跨平台 Turbo Native Modules](./pure-cxx-modules)。但它也适用于组件和旧架构模块和组件。您需要调整需要复制和更新的文件。
+
+
+
+1. **[旧架构模块和组件不需要]** 将应用中 `specs` 文件夹中的代码移动到 `create-react-native-library` 文件夹创建的 `src` 文件夹中。
+2. 更新 `index.ts` 文件以正确导出 Turbo Native Module 规范,使其可从库访问。例如:
+
+```ts
+import NativeSampleModule from './NativeSampleModule';
+
+export default NativeSampleModule;
+```
+
+3. 复制原生模块:
+ - 如果有的话,用您在应用中为原生模块编写的代码替换 `android/src/main/java/com/` 中的代码。
+ - 如果有的话,用您在应用中为原生模块编写的代码替换 `ios` 文件夹中的代码。
+ - 如果有的话,用您在应用中为原生模块编写的代码替换 `cpp` 文件夹中的代码。
+
+4. **[旧架构模块和组件不需要]** 将所有从旧规范名称到新规范名称的引用更新,即库的 `package.json` 的 `codegenConfig` 字段中定义的名称。例如,如果在应用 `package.json` 中您将 `AppSpecs` 设置为 `codegenConfig.name`,而在库中它被称为 `RNNativeSampleModuleSpec`,则必须将每次出现的 `AppSpecs` 替换为 `RNNativeSampleModuleSpec`。
+
+就是这样!您已将所有所需代码从应用中移出并放入单独的库中。
+
+## 测试您的库
+
+`create-react-native-library` 附带一个有用的示例应用程序,该应用程序已经配置为与库正常工作。这是测试它的好方法!
+
+如果您查看 `example` 文件夹,您可以找到与您可以从 [`react-native-community/template`](https://github.com/react-native-community/template) 创建的新 React Native 应用程序相同的结构。
+
+要测试您的库:
+
+1. 导航到 `example` 文件夹。
+2. 运行 `yarn install` 以安装所有依赖项。
+3. 仅对于 iOS,您需要安装 CocoaPods:`cd ios && pod install`。
+4. 从 `example` 文件夹使用 `yarn android` 构建并运行 Android。
+5. 从 `example` 文件夹使用 `yarn ios` 构建并运行 iOS。
+
+## 将您的库用作本地模块
+
+在某些情况下,您可能希望将库作为应用的本地模块重用,而不将其发布到 NPM。
+
+在这种情况下,您可能最终会遇到库作为应用的兄弟目录的场景。
+
+```shell
+Development
+├── App
+└── Library
+```
+
+您也可以在这种情况下使用 `create-react-native-library` 创建的库。
+
+1. 通过导航到 `App` 文件夹并运行 `yarn add ../Library` 将库添加到您的应用。
+2. 仅对于 iOS,导航到 `App/ios` 文件夹并运行 `bundle exec pod install` 以安装您的依赖项。
+3. 更新 `App.tsx` 代码以导入库中的代码。例如:
+
+```tsx
+import NativeSampleModule from '../Library/src/index';
+```
+
+如果您现在运行您的应用,Metro 将找不到它需要提供给应用的 JS 文件。这是因为 metro 将从 `App` 文件夹开始运行,并且无法访问位于 `Library` 文件夹中的 JS 文件。要解决此问题,让我们按如下方式更新 `metro.config.js` 文件
+
+```diff
+const {getDefaultConfig, mergeConfig} = require('@react-native/metro-config');
+
+/**
+ * Metro configuration
+ * https://reactnative.dev/docs/metro
+ *
+ * @type {import('metro-config').MetroConfig}
+ */
++ const path = require('path');
+
+- const config = {}
++ const config = {
++ // Make Metro able to resolve required external dependencies
++ watchFolders: [
++ path.resolve(__dirname, '../Library'),
++ ],
++ resolver: {
++ extraNodeModules: {
++ 'react-native': path.resolve(__dirname, 'node_modules/react-native'),
++ },
++ },
++};
+
+module.exports = mergeConfig(getDefaultConfig(__dirname), config);
+```
+
+`watchFolders` 配置告诉 Metro 监视一些额外路径中的文件和更改,在这种情况下是 `../Library` 路径,其中包含您需要的 `src/index` 文件。
+`resolver` 属性是为库提供应用使用的 React Native 代码所必需的。库可能会引用和导入来自 React Native 的代码:如果没有额外的解析器,库中的导入将失败。
+
+此时,您可以像往常一样构建和运行您的应用:
+
+- 从 `example` 文件夹使用 `yarn android` 构建并运行 Android。
+- 从 `example` 文件夹使用 `yarn ios` 构建并运行 iOS。
+
+## 在 NPM 上发布库
+
+由于 `create-react-native-library`,在 NPM 上发布所有内容的设置已经就位。
+
+1. 在您的模块中安装依赖项 `yarn install`。
+2. 运行 `yarn prepare` 构建库。
+3. 使用 `yarn release` 发布它。
+
+一段时间后,您将在 NPM 上找到您的库。要验证这一点,请运行:
+
+```bash
+npm view
+```
+
+其中 `package.name` 是您在库初始化期间在 `package.json` 文件中设置的 `name`。
+
+现在,您可以通过运行以下命令在应用程序中安装该库:
+
+```bash
+yarn add
+```
+
+:::note
+仅对于 iOS,每当您安装带有一些原生代码的新模块时,您必须重新安装 CocoaPods,方法是运行 `bundle exec pod install`(推荐)或 `pod install`(如果您不使用 Ruby 的 Bundler,则不推荐)。
+:::
+
+恭喜!您发布了您的第一个 React Native 库。
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/custom-cxx-types.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/custom-cxx-types.md
new file mode 100644
index 00000000000..94db3e21b3f
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/custom-cxx-types.md
@@ -0,0 +1,422 @@
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+# Advanced: Custom C++ Types
+
+:::note
+This guide assumes that you are familiar with the [**Pure C++ Turbo Native Modules**](pure-cxx-modules.md) guide. This will build on top of that guide.
+:::
+
+C++ Turbo Native Modules support [bridging functionality](https://github.com/facebook/react-native/tree/main/packages/react-native/ReactCommon/react/bridging) for most `std::` standard types. You can use most of those types in your modules without any additional code required.
+
+If you want to add support for new and custom types in your app or library, you need to provide the necessary `bridging` header file.
+
+## Adding a New Custom: Int64
+
+C++ Turbo Native Modules don't support `int64_t` numbers yet - because JavaScript doesn't support numbers greater 2^53. To represent numbers greater than 2^53, we can use a `string` type in JS and automatically convert it to `int64_t` in C++.
+
+### 1. Create the Bridging Header file
+
+The first step to support a new custom type is to define the bridging header that takes care of converting the type **from** the JS representation to the C++ representation, and from the C++ representation **to** the JS one.
+
+1. In the `shared` folder, add a new file called `Int64.h`
+2. Add the following code to that file:
+
+```cpp title="Int64.h"
+#pragma once
+
+#include
+
+namespace facebook::react {
+
+template <>
+struct Bridging {
+ // Converts from the JS representation to the C++ representation
+ static int64_t fromJs(jsi::Runtime &rt, const jsi::String &value) {
+ try {
+ size_t pos;
+ auto str = value.utf8(rt);
+ auto num = std::stoll(str, &pos);
+ if (pos != str.size()) {
+ throw std::invalid_argument("Invalid number"); // don't support alphanumeric strings
+ }
+ return num;
+ } catch (const std::logic_error &e) {
+ throw jsi::JSError(rt, e.what());
+ }
+ }
+
+ // Converts from the C++ representation to the JS representation
+ static jsi::String toJs(jsi::Runtime &rt, int64_t value) {
+ return bridging::toJs(rt, std::to_string(value));
+ }
+};
+
+}
+```
+
+The key components for your custom bridging header are:
+
+- Explicit specialization of the `Bridging` struct for your custom type. In this case, the template specify the `int64_t` type.
+- A `fromJs` function to convert from the JS representation to the C++ representation
+- A `toJs` function to convert from the C++ representation to the JS representation
+
+:::note
+On iOS, remember to add the `Int64.h` file to the Xcode project.
+:::
+
+### 2. Modify the JS Spec
+
+Now, we can modify the JS spec to add a method that uses the new type. As usual, we can use either Flow or TypeScript for our specs.
+
+1. Open the `specs/NativeSampleTurbomodule`
+2. Modify the spec as follows:
+
+
+
+
+```diff title="NativeSampleModule.ts"
+import {TurboModule, TurboModuleRegistry} from 'react-native';
+
+export interface Spec extends TurboModule {
+ readonly reverseString: (input: string) => string;
++ readonly cubicRoot: (input: string) => number;
+}
+
+export default TurboModuleRegistry.getEnforcing(
+ 'NativeSampleModule',
+);
+```
+
+
+
+
+```diff title="NativeSampleModule.js"
+// @flow
+import type {TurboModule} from 'react-native';
+import { TurboModuleRegistry } from "react-native";
+
+export interface Spec extends TurboModule {
+ +reverseString: (input: string) => string;
++ +cubicRoot: (input: string) => number;
+}
+
+export default (TurboModuleRegistry.getEnforcing(
+ "NativeSampleModule"
+): Spec);
+```
+
+
+
+
+In this files, we are defining the function that needs to be implemented in C++.
+
+### 3. Implement the Native Code
+
+Now, we need to implement the function that we declared in the JS specification.
+
+1. Open the `specs/NativeSampleModule.h` file and apply the following changes:
+
+```diff title="NativeSampleModule.h"
+#pragma once
+
+#include
+#include
+#include
+
++ #include "Int64.h"
+
+namespace facebook::react {
+
+class NativeSampleModule : public NativeSampleModuleCxxSpec {
+public:
+ NativeSampleModule(std::shared_ptr jsInvoker);
+
+ std::string reverseString(jsi::Runtime& rt, std::string input);
++ int32_t cubicRoot(jsi::Runtime& rt, int64_t input);
+};
+
+} // namespace facebook::react
+
+```
+
+2. Open the `specs/NativeSampleModule.cpp` file and apply the implement the new function:
+
+```diff title="NativeSampleModule.cpp"
+#include "NativeSampleModule.h"
++ #include
+
+namespace facebook::react {
+
+NativeSampleModule::NativeSampleModule(std::shared_ptr jsInvoker)
+ : NativeSampleModuleCxxSpec(std::move(jsInvoker)) {}
+
+std::string NativeSampleModule::reverseString(jsi::Runtime& rt, std::string input) {
+ return std::string(input.rbegin(), input.rend());
+}
+
++int32_t NativeSampleModule::cubicRoot(jsi::Runtime& rt, int64_t input) {
++ return std::cbrt(input);
++}
+
+} // namespace facebook::react
+```
+
+The implementation imports the `` C++ library to perform mathematical operations, then it implements the `cubicRoot` function using the `cbrt` primitive from the `` module.
+
+### 4. Test your code in Your App
+
+Now, we can test the code in our app.
+
+First, we need to update the `App.tsx` file to use the new method from the TurboModule. Then, we can build our apps in Android and iOS.
+
+1. Open the `App.tsx` code apply the following changes:
+
+```diff title="App.tsx"
+// ...
++ const [cubicSource, setCubicSource] = React.useState('')
++ const [cubicRoot, setCubicRoot] = React.useState(0)
+ return (
+
+
+
+ Welcome to C++ Turbo Native Module Example
+
+ Write down here the text you want to revert
+
+
+ Reversed text: {reversedValue}
++ For which number do you want to compute the Cubic Root?
++
++ setCubicRoot(SampleTurboModule.cubicRoot(cubicSource))} />
++ The cubic root is: {cubicRoot}
+
+
+ );
+}
+//...
+```
+
+2. To test the app on Android, run `yarn android` from the root folder of your project.
+3. To test the app on iOS, run `yarn ios` from the root folder of your project.
+
+## Adding a New Structured Custom Type: Address
+
+The approach above can be generalized to any kind of type. For structured types, React Native provides some helper functions that make it easier to bridge them from JS to C++ and vice versa.
+
+Let's assume that we want to bridge a custom `Address` type with the following properties:
+
+```ts
+interface Address {
+ street: string;
+ num: number;
+ isInUS: boolean;
+}
+```
+
+### 1. Define the type in the specs
+
+For the first step, let's define the new custom type in the JS specs, so that Codegen can output all the supporting code. In this way, we don't have to manually write the code.
+
+1. Open the `specs/NativeSampleModule` file and add the following changes.
+
+
+
+
+```diff title="NativeSampleModule (Add Address type and validateAddress function)"
+import {TurboModule, TurboModuleRegistry} from 'react-native';
+
++export type Address = {
++ street: string,
++ num: number,
++ isInUS: boolean,
++};
+
+export interface Spec extends TurboModule {
+ readonly reverseString: (input: string) => string;
++ readonly validateAddress: (input: Address) => boolean;
+}
+
+export default TurboModuleRegistry.getEnforcing(
+ 'NativeSampleModule',
+);
+```
+
+
+
+
+```diff title="NativeSampleModule (Add Address type and validateAddress function)"
+
+// @flow
+import type {TurboModule} from 'react-native';
+import { TurboModuleRegistry } from "react-native";
+
++export type Address = {
++ street: string,
++ num: number,
++ isInUS: boolean,
++};
+
+
+export interface Spec extends TurboModule {
+ +reverseString: (input: string) => string;
++ +validateAddress: (input: Address) => boolean;
+}
+
+export default (TurboModuleRegistry.getEnforcing(
+ "NativeSampleModule"
+): Spec);
+```
+
+
+
+
+This code defines the new `Address` type and defines a new `validateAddress` function for the Turbo Native Module. Notice that the `validateFunction` requires an `Address` object as parameter.
+
+It is also possible to have functions that return custom types.
+
+### 2. Define the bridging code
+
+From the `Address` type defined in the specs, Codegen will generate two helper types: `NativeSampleModuleAddress` and `NativeSampleModuleAddressBridging`.
+
+The first type is the definition of the `Address`. The second type contains all the infrastructure to bridge the custom type from JS to C++ and vice versa. The only extra step we need to add is to define the `Bridging` structure that extends the `NativeSampleModuleAddressBridging` type.
+
+1. Open the `shared/NativeSampleModule.h` file
+2. Add the following code in the file:
+
+```diff title="NativeSampleModule.h (Bridging the Address type)"
+#include "Int64.h"
+#include
+#include
+
+namespace facebook::react {
++ using Address = NativeSampleModuleAddress;
+
++ template <>
++ struct Bridging
++ : NativeSampleModuleAddressBridging {};
+ // ...
+}
+```
+
+This code defines an `Address` typealias for the generic type `NativeSampleModuleAddress`. **The order of the generics matters**: the first template argument refers to the first data type of the struct, the second refers to the second, and so forth.
+
+Then, the code adds the `Bridging` specialization for the new `Address` type, by extending `NativeSampleModuleAddressBridging` that is generated by Codegen.
+
+:::note
+There is a convention that is followed to generate this types:
+
+- The first part of the name is always the type of the module. `NativeSampleModule`, in this example.
+- The second part of the name is always the name of the JS type defined in the specs. `Address`, in this example.
+ :::
+
+### 3. Implement the Native Code
+
+Now, we need to implement the `validateAddress` function in C++. First, we need to add the function declaration into the `.h` file, and then we can implement it in the `.cpp` file.
+
+1. Open the `shared/NativeSampleModule.h` file and add the function definition
+
+```diff title="NativeSampleModule.h (validateAddress function prototype)"
+ std::string reverseString(jsi::Runtime& rt, std::string input);
+
++ bool validateAddress(jsi::Runtime &rt, jsi::Object input);
+};
+
+} // namespace facebook::react
+```
+
+2. Open the `shared/NativeSampleModule.cpp` file and add the function implementation
+
+```cpp title="NativeSampleModule.cpp (validateAddress implementation)"
+bool NativeSampleModule::validateAddress(jsi::Runtime &rt, jsi::Object input) {
+ std::string street = input.getProperty(rt, "street").asString(rt).utf8(rt);
+ int32_t number = input.getProperty(rt, "num").asNumber();
+
+ return !street.empty() && number > 0;
+}
+```
+
+In the implementation, the object that represents the `Address` is a `jsi::Object`. To extract the values from this object, we need to use the accessors provided by `JSI`:
+
+- `getProperty()` retrieves the property from and object by name.
+- `asString()` converts the property to `jsi::String`.
+- `utf8()` converts the `jsi::String` to a `std::string`.
+- `asNumber()` converts the property to a `double`.
+
+Once we manually parsed the object, we can implement the logic that we need.
+
+:::note
+If you want to learn more about `JSI` and how it works, have a look at this [great talk](https://youtu.be/oLmGInjKU2U?feature=shared) from App.JS 2024
+:::
+
+### 4. Testing the code in the app
+
+To test the code in the app, we have to modify the `App.tsx` file.
+
+1. Open the `App.tsx` file. Remove the content of the `App()` function.
+2. Replace the body of the `App()` function with the following code:
+
+```tsx title="App.tsx (App function body replacement)"
+const [street, setStreet] = React.useState('');
+const [num, setNum] = React.useState('');
+const [isValidAddress, setIsValidAddress] = React.useState<
+ boolean | null
+>(null);
+
+const onPress = () => {
+ let houseNum = parseInt(num, 10);
+ if (isNaN(houseNum)) {
+ houseNum = -1;
+ }
+ const address = {
+ street,
+ num: houseNum,
+ isInUS: false,
+ };
+ const result = SampleTurboModule.validateAddress(address);
+ setIsValidAddress(result);
+};
+
+return (
+
+
+
+ Welcome to C Turbo Native Module Example
+
+ Address:
+
+ Number:
+
+
+ {isValidAddress != null && (
+
+ Your address is {isValidAddress ? 'valid' : 'not valid'}
+
+ )}
+
+
+);
+```
+
+Congratulation! 🎉
+
+You bridged your first types from JS to C++.
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/direct-manipulation.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/direct-manipulation.md
new file mode 100644
index 00000000000..6708a643cba
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/direct-manipulation.md
@@ -0,0 +1,128 @@
+---
+id: direct-manipulation-new-architecture
+title: Direct Manipulation
+---
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+It is sometimes necessary to make changes directly to a component without using state/props to trigger a re-render of the entire subtree. When using React in the browser for example, you sometimes need to directly modify a DOM node, and the same is true for views in mobile apps. `setNativeProps` is the React Native equivalent to setting properties directly on a DOM node.
+
+:::caution
+Use `setNativeProps` when frequent re-rendering creates a performance bottleneck!
+
+Direct manipulation will not be a tool that you reach for frequently. You will typically only be using it for creating continuous animations to avoid the overhead of rendering the component hierarchy and reconciling many views.
+`setNativeProps` is imperative and stores state in the native layer (DOM, UIView, etc.) and not within your React components, which makes your code more difficult to reason about.
+
+Before you use it, try to solve your problem with `setState` and [`shouldComponentUpdate`](https://react.dev/reference/react/Component#shouldcomponentupdate).
+:::
+
+## setNativeProps to edit TextInput value
+
+Another very common use case of `setNativeProps` is to edit the value of the TextInput. The `controlled` prop of TextInput can sometimes drop characters when the `bufferDelay` is low and the user types very quickly. Some developers prefer to skip this prop entirely and instead use `setNativeProps` to directly manipulate the TextInput value when necessary.
+
+For example, the following code demonstrates editing the input when you tap a button:
+
+
+
+
+```SnackPlayer name=setNativeProps%20on%20TextInput&ext=js
+import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+ StyleSheet,
+ TextInput,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+
+const App = () => {
+ const inputRef = useRef(null);
+ const editText = useCallback(() => {
+ inputRef.current.setNativeProps({text: 'Edited Text'});
+ }, []);
+
+ return (
+
+
+
+ Edit text
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ input: {
+ height: 50,
+ width: 200,
+ marginHorizontal: 20,
+ borderWidth: 1,
+ borderColor: '#ccc',
+ },
+});
+
+export default App;
+```
+
+
+
+
+```SnackPlayer name=Clear%20text&ext=tsx
+import React from 'react';
+import {useCallback, useRef} from 'react';
+import {
+ StyleSheet,
+ TextInput,
+ Text,
+ TouchableOpacity,
+ View,
+} from 'react-native';
+
+const App = () => {
+ const inputRef = useRef(null);
+ const editText = useCallback(() => {
+ inputRef.current?.setNativeProps({text: 'Edited Text'});
+ }, []);
+
+ return (
+
+
+
+ Edit text
+
+
+ );
+};
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ input: {
+ height: 50,
+ width: 200,
+ marginHorizontal: 20,
+ borderWidth: 1,
+ borderColor: '#ccc',
+ },
+});
+
+export default App;
+```
+
+
+
+
+You can use the [`clear`](../textinput#clear) method to clear the `TextInput` which clears the current input text using the same approach.
+
+## Avoiding conflicts with the render function
+
+If you update a property that is also managed by the render function, you might end up with some unpredictable and confusing bugs because anytime the component re-renders and that property changes, whatever value was previously set from `setNativeProps` will be completely ignored and overridden.
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/fabric-component-native-commands.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/fabric-component-native-commands.md
new file mode 100644
index 00000000000..ca87360ba3a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/fabric-component-native-commands.md
@@ -0,0 +1,427 @@
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+# Invoking native functions on your native component
+
+In the [base guide](/docs/fabric-native-components-introduction) to write a new Native Component, you have explored how to create a new component, how to pass properties from the JS side to the native side, and how to emit events from native side to JS.
+
+Custom components can also call some of the functions implemented in the native code imperatively, to achieve some more advanced functionalities, such as programmatically reload a web page.
+
+In this guide you'll learn how to achieve this, by using a new concept: Native Commands.
+
+This guide starts from the [Native Components](/docs/fabric-native-components-introduction) guide and assumes that you are familiar with it and that you are familiar with [Codegen](/docs/next/the-new-architecture/what-is-codegen).
+
+## 1. Update your component specs
+
+The first step is to update the component spec to declare the `NativeCommand`.
+
+
+
+
+Update the `WebViewNativeComponent.ts` as it follows:
+
+```diff title="Demo/specs/WebViewNativeComponent.ts"
+import type {HostComponent, ViewProps} from 'react-native';
+import type {BubblingEventHandler} from 'react-native/Libraries/Types/CodegenTypes';
+import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
++import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
+
+type WebViewScriptLoadedEvent = {
+ result: 'success' | 'error';
+};
+
+export interface NativeProps extends ViewProps {
+ sourceURL?: string;
+ onScriptLoaded?: BubblingEventHandler | null;
+}
+
++interface NativeCommands {
++ reload: (viewRef: React.ElementRef>) => void;
++}
+
++export const Commands: NativeCommands = codegenNativeCommands({
++ supportedCommands: ['reload'],
++});
+
+export default codegenNativeComponent(
+ 'CustomWebView',
+) as HostComponent;
+```
+
+
+
+
+Update the `WebViewNativeComponent.js` as it follows:
+
+```diff title="Demo/specs/WebViewNativeComponent.js"
+// @flow strict-local
+
+import type {HostComponent, ViewProps} from 'react-native';
+import type {BubblingEventHandler} from 'react-native/Libraries/Types/CodegenTypes';
+import codegenNativeComponent from 'react-native/Libraries/Utilities/codegenNativeComponent';
++import codegenNativeCommands from 'react-native/Libraries/Utilities/codegenNativeCommands';
+
+type WebViewScriptLoadedEvent = $ReadOnly<{|
+ result: "success" | "error",
+|}>;
+
+type NativeProps = $ReadOnly<{|
+ ...ViewProps,
+ sourceURL?: string;
+ onScriptLoaded?: BubblingEventHandler?;
+|}>;
+
++interface NativeCommands {
++ reload: (viewRef: React.ElementRef>) => void;
++}
+
++export const Commands: NativeCommands = codegenNativeCommands({
++ supportedCommands: ['reload'],
++});
+
+export default (codegenNativeComponent(
+ 'CustomWebView',
+): HostComponent);
+
+```
+
+
+
+
+These changes requires you to:
+
+1. Import the `codegenNativeCommands` function from `react-native`. This instruct codegen that it has to generate the code for `NativeCommands`
+2. Define an interface that contains the methods we want to invoke in native. All the Native Commands must have a first parameter of type `React.ElementRef`.
+3. Export the `Commands` variable that is the result of the invocation of `codegenNativeCommands`, passing a list of the supported commands.
+
+:::warning
+In TypeScript, the `React.ElementRef` is deprecated. The correct type to use is actually `React.ComponentRef`. However, due to a bug in Codegen, using `ComponentRef` will crash the app. We have the fix already, but we need to release a new version of React Native to apply it.
+:::
+
+## 2. Update the App code to use the new command
+
+Now you can use the command in the the app.
+
+
+
+
+Open the `App.tsx` file and modify it as it follows:
+
+```diff title="App.tsx"
+import React from 'react';
+-import {Alert, StyleSheet, View} from 'react-native';
+-import WebView from '../specs/WebViewNativeComponent';
++import {Alert, StyleSheet, Pressable, Text, View} from 'react-native';
++import WebView, {Commands} from '../specs/WebViewNativeComponent';
+
+function App(): React.JSX.Element {
++ const webViewRef = React.useRef | null>(null);
++
++ const refresh = () => {
++ if (webViewRef.current) {
++ Commands.reload(webViewRef.current);
++ }
++ };
+
+ return (
+
+ {
+ Alert.alert('Page Loaded');
+ }}
+ />
++
++
++ {({pressed}) => (
++ !pressed ? Refresh : Refresh ) }
++
++
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ alignContent: 'center',
+ },
+ webview: {
+ width: '100%',
+- height: '100%',
++ height: '90%',
+ },
++ tabbar: {
++ flex: 1,
++ backgroundColor: 'gray',
++ width: '100%',
++ alignItems: 'center',
++ alignContent: 'center',
++ },
++ button: {
++ margin: 10,
++ },
++ buttonText: {
++ fontSize: 20,
++ fontWeight: 'bold',
++ color: '#00D6FF',
++ width: '100%',
++ },
++ buttonTextPressed: {
++ fontSize: 20,
++ fontWeight: 'bold',
++ color: '#00D6FF77',
++ width: '100%',
++ },
+});
+
+export default App;
+```
+
+
+
+
+Open the `App.tsx` file and modify it as it follows:
+
+```diff title="App.jsx"
+import React from 'react';
+-import {Alert, StyleSheet, View} from 'react-native';
+-import WebView from '../specs/WebViewNativeComponent';
++import {Alert, StyleSheet, Pressable, Text, View} from 'react-native';
++import WebView, {Commands} from '../specs/WebViewNativeComponent';
+
+function App(): React.JSX.Element {
++ const webViewRef = React.useRef | null>(null);
++
++ const refresh = () => {
++ if (webViewRef.current) {
++ Commands.reload(webViewRef.current);
++ }
++ };
+
+ return (
+
+ {
+ Alert.alert('Page Loaded');
+ }}
+ />
++
++
++ {({pressed}) => (
++ !pressed ? Refresh : Refresh ) }
++
++
+
+ );
+}
+
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ alignItems: 'center',
+ alignContent: 'center',
+ },
+ webview: {
+ width: '100%',
+- height: '100%',
++ height: '90%',
+ },
++ tabbar: {
++ flex: 1,
++ backgroundColor: 'gray',
++ width: '100%',
++ alignItems: 'center',
++ alignContent: 'center',
++ },
++ button: {
++ margin: 10,
++ },
++ buttonText: {
++ fontSize: 20,
++ fontWeight: 'bold',
++ color: '#00D6FF',
++ width: '100%',
++ },
++ buttonTextPressed: {
++ fontSize: 20,
++ fontWeight: 'bold',
++ color: '#00D6FF77',
++ width: '100%',
++ },
+});
+
+export default App;
+```
+
+
+
+
+The relevant changes here are the following:
+
+1. Import the `Commands` const from the spec file. The Command is an object that let us call the methods we have in native.
+2. Declare a ref to the `WebView` custom native component using `useRef`. You need to pass this ref to the native command.
+3. Implement the `refresh` function. This function checks that the WebView's ref is not null and if not, it calls the command.
+4. Add a pressable to call the command when the user taps on the button.
+
+The remaining changes are regular React changes to add a `Pressable` and to style the view so it looks nicer.
+
+## 3. Rerun Codegen
+
+Now that the specs are updated and the code is ready to use the command, it is time to implement the Native code. However, before diving into writing native code, you have to rerun codegen, to let it generate the new types that are needed by the Native code.
+
+
+
+Codegen is executed through the `generateCodegenArtifactsFromSchema` Gradle task:
+
+```bash
+cd android
+./gradlew generateCodegenArtifactsFromSchema
+
+BUILD SUCCESSFUL in 837ms
+14 actionable tasks: 3 executed, 11 up-to-date
+```
+
+This is automatically run when you build your Android application.
+
+
+Codegen is run as part of the script phases that's automatically added to the project generated by CocoaPods.
+
+```bash
+cd ios
+bundle install
+bundle exec pod install
+```
+
+The output will look like this:
+
+```shell
+...
+Framework build type is static library
+[Codegen] Adding script_phases to ReactCodegen.
+[Codegen] Generating ./build/generated/ios/ReactCodegen.podspec.json
+[Codegen] Analyzing /Users/me/src/TurboModuleExample/package.json
+[Codegen] Searching for codegen-enabled libraries in the app.
+[Codegen] Found TurboModuleExample
+[Codegen] Searching for codegen-enabled libraries in the project dependencies.
+[Codegen] Found react-native
+...
+```
+
+
+
+
+## 4. Implement the Native Code
+
+Now it's time to implement the native changes that will enable your JS to directly invoke methods on your native view.
+
+
+
+
+To let your view respond to the Native Command, you only have to modify the ReactWebViewManager.
+
+If you try to build right now, the build will fail, because the current `ReactWebViewManager` does not implement the new `reload` method.
+To fix the build error, let's modify the `ReactWebViewManager` to implement it.
+
+
+
+
+```diff title="ReactWebViewManager.java"
+
+//...
+ @ReactProp(name = "sourceUrl")
+ @Override
+ public void setSourceURL(ReactWebView view, String sourceURL) {
+ if (sourceURL == null) {
+ view.emitOnScriptLoaded(ReactWebView.OnScriptLoadedEventResult.error);
+ return;
+ }
+ view.loadUrl(sourceURL, new HashMap<>());
+ }
+
++ @Override
++ public void reload(ReactWebView view) {
++ view.reload();
++ }
+
+ public static final String REACT_CLASS = "CustomWebView";
+//...
+```
+
+
+
+
+```diff title="ReactWebViewManager.kt"
+ @ReactProp(name = "sourceUrl")
+ override fun setSourceURL(view: ReactWebView, sourceURL: String?) {
+ if (sourceURL == null) {
+ view.emitOnScriptLoaded(ReactWebView.OnScriptLoadedEventResult.error)
+ return;
+ }
+ view.loadUrl(sourceURL, emptyMap())
+ }
+
++ override fun reload(view: ReactWebView) {
++ view.reload()
++ }
+
+ companion object {
+ const val REACT_CLASS = "CustomWebView"
+ }
+```
+
+
+
+
+In this case, it's enough to call directly the `view.reload()` method because our ReactWebView inherits from the Android's `WebView` and it has a reload method directly available. If you are implementing a custom function, that is not available in your custom view, you might also have to implement the required method in the Android's View that is managed by the React Native's `ViewManager`.
+
+
+
+
+To let your view respond to the Native Command, we need to implement a couple of methods on iOS.
+
+Let's open the `RCTWebView.mm` file and let's modify it as it follows:
+
+```diff title="RCTWebView.mm"
+ // Event emitter convenience method
+ - (const CustomWebViewEventEmitter &)eventEmitter
+ {
+ return static_cast(*_eventEmitter);
+ }
+
++ - (void)handleCommand:(const NSString *)commandName args:(const NSArray *)args
++ {
++ RCTCustomWebViewHandleCommand(self, commandName, args);
++ }
++
++ - (void)reload
++ {
++ [_webView reloadFromOrigin];
++ }
+
+ + (ComponentDescriptorProvider)componentDescriptorProvider
+ {
+ return concreteComponentDescriptorProvider();
+ }
+```
+
+To make your view respond to the Native Commands, you need to apply the following changes:
+
+1. Add a `handleCommand:args` function. This function is invoked by the components infrastructure to handle the commands. The function implementation is similar for every component: you need to call an `RCTHandleCommand` function that is generated by Codegen for you. The `RCTHandleCommand` perform a bunch of validation, verifying that the command that we need to invoke is among the supported ones and that the parameters passed matches the one expected. If all the checks pass, the `RCTHandleCommand` will then invoke the proper native method.
+2. Implement the `reload` method. In this example, the `reload` method calls the `reloadFromOrigin` function of the WebKit's WebView.
+
+
+
+
+## 5. Run your app
+
+Finally, you can run your app with the usual commands. Once the app is running, you can tap on the refresh button to see the page getting reloaded.
+
+| Android | iOS |
+| ------------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------- |
+| | |
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/layout-measurements.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/layout-measurements.md
new file mode 100644
index 00000000000..cc693a99b0c
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/layout-measurements.md
@@ -0,0 +1,53 @@
+# Measuring the Layout
+
+Sometimes, you need to measure the current layout to apply some changes to the overall layout or to make decisions and call some specific logic.
+
+React Native provides some native methods to know what are the measurements of the views.
+
+The best way to invoke those methods is in a `useLayoutEffect` hook: this will give you the most recent values for those measurements and it will let you apply changes in the same frame when the measurements are computed.
+
+Typical code will look like this:
+
+```tsx
+function AComponent(children) {
+ const targetRef = React.useRef(null)
+
+ useLayoutEffect(() => {
+ targetRef.current?.measure((x, y, width, height, pageX, pageY) => {
+ //do something with the measurements
+ });
+ }, [ /* add dependencies here */]);
+
+ return (
+
+ {children}
+
+ );
+}
+```
+
+:::note
+The methods described here are available on most of the default components provided by React Native. However, they are _not_ available on composite components that aren't directly backed by a native view. This will generally include most components that you define in your own app.
+:::
+
+## measure(callback)
+
+Determines the location on screen (`x` and `y`), `width`, and `height` in the viewport of the given view. Returns the values via an async callback. If successful, the callback will be called with the following arguments:
+
+- `x`: the `x` coordinate of the origin (top-left corner) of the measured view in the viewport.
+- `y`: the `y` coordinate of the origin (top-left corner) of the measured view in the viewport.
+- `width`: the `width` of the view.
+- `height`: the `height` of the view.
+- `pageX`: the `x` coordinate of the view in the viewport (typically the whole screen).
+- `pageY`: the `y` coordinate of the view in the viewport (typically the whole screen).
+
+Also the `width` and `height` returned by `measure()` are the `width` and `height` of the component in the viewport.
+
+## measureInWindow(callback)
+
+Determines the location (`x` and `y`) of the given view in the window and returns the values via an async callback. If the React root view is embedded in another native view, this will give you the absolute coordinates. If successful, the callback will be called with the following arguments:
+
+- `x`: the `x` coordinate of the view in the current window.
+- `y`: the `y` coordinate of the view in the current window.
+- `width`: the `width` of the view.
+- `height`: the `height` of the view.
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/native-modules-custom-events.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/native-modules-custom-events.md
new file mode 100644
index 00000000000..490e021ccfe
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/native-modules-custom-events.md
@@ -0,0 +1,376 @@
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+# Emitting Events in Native Modules
+
+In some circustamces, you may want to have a Native Module that listen to some events in the platform layer and then emit them to the JavaScript layer, to let you application react to such native events. In other cases, you might have long running operations that can emits events so that the UI can be updated when those happen.
+
+Both are good use cases for emitting events from a Native Modules. In this guide, you'll learn how to do that.
+
+## Emitting an Event when a new key added to the storage
+
+In this example, you will learn how to emit an event when a new key is added to the storage. Changing the value of the key will not emit the event, but adding a new key will.
+
+This guide starts from the [Native Module](/docs/next/turbo-native-modules-introduction) guide.
+Make sure to be familiar with that guide before diving into this one, potentially implementing the example in the guide.
+
+## Step 1: Update the Specs of NativeLocalStorage
+
+The first step would be to update the specs of the `NativeLocalStorage` specs to let React Native aware that the module can emit events.
+
+
+
+
+Open the `NativeLocalStorage.ts` file and update it as it follows:
+
+```diff title="NativeLocalStorage.ts"
++import type {TurboModule, CodegenTypes} from 'react-native';
+import {TurboModuleRegistry} from 'react-native';
+
++export type KeyValuePair = {
++ key: string,
++ value: string,
++}
+
+export interface Spec extends TurboModule {
+ setItem(value: string, key: string): void;
+ getItem(key: string): string | null;
+ removeItem(key: string): void;
+ clear(): void;
+
++ readonly onKeyAdded: CodegenTypes.EventEmitter;
+}
+
+export default TurboModuleRegistry.getEnforcing(
+ 'NativeLocalStorage',
+);
+```
+
+
+
+
+Open the `NativeLocalStorage.js` file and update it as it follows:
+
+```diff title="NativeLocalStorage.js"
+
+// @flow
++import type {TurboModule, CodegenTypes} from 'react-native';
+import {TurboModule, TurboModuleRegistry} from 'react-native';
+
++export type KeyValuePair = {
++ key: string,
++ value: string,
++}
+
+export interface Spec extends TurboModule {
+ setItem(value: string, key: string): void;
+ getItem(key: string): ?string;
+ removeItem(key: string): void;
+ clear(): void;
++ onKeyAdded: CodegenTypes.EventEmitter
+}
+export default (TurboModuleRegistry.get(
+ 'NativeLocalStorage'
+): ?Spec);
+```
+
+
+
+
+With the `import type` statement, you are importing the `CodegenTypes` from `react-native`, which includes the `EventEmitter` type. This allows you to define the `onKeyAdded` property using `CodegenTypes.EventEmitter`, specifying that the event will emit a payload of type `KeyValuePair`.
+
+When the event is emitted, you expect for it to receive a parameter of type `string`.
+
+## Step 2: Generate Codegen
+
+Given that you have updated the specs for your Native Module, you now have to rerun Codegen to generate the artifacts in the native code.
+
+This is the same process presented in the Native Modules guide.
+
+
+
+Codegen is executed through the `generateCodegenArtifactsFromSchema` Gradle task:
+
+```bash
+cd android
+./gradlew generateCodegenArtifactsFromSchema
+
+BUILD SUCCESSFUL in 837ms
+14 actionable tasks: 3 executed, 11 up-to-date
+```
+
+This is automatically run when you build your Android application.
+
+
+Codegen is run as part of the script phases that's automatically added to the project generated by CocoaPods.
+
+```bash
+cd ios
+bundle install
+bundle exec pod install
+```
+
+The output will look like this:
+
+```shell
+...
+Framework build type is static library
+[Codegen] Adding script_phases to ReactCodegen.
+[Codegen] Generating ./build/generated/ios/ReactCodegen.podspec.json
+[Codegen] Analyzing /Users/me/src/TurboModuleExample/package.json
+[Codegen] Searching for Codegen-enabled libraries in the app.
+[Codegen] Found TurboModuleExample
+[Codegen] Searching for Codegen-enabled libraries in the project dependencies.
+[Codegen] Found react-native
+...
+```
+
+
+
+
+## Step 3: Update the App code
+
+Now, it's time to update the code of the App to handle the new event.
+
+Open the `App.tsx` file and modify it as it follows:
+
+```diff title="App.tsx"
+import React from 'react';
+import {
++ Alert,
++ EventSubscription,
+ SafeAreaView,
+ StyleSheet,
+ Text,
+ TextInput,
+ Button,
+} from 'react-native';
+
+import NativeLocalStorage from './specs/NativeLocalStorage';
+
+const EMPTY = '';
+
+function App(): React.JSX.Element {
+ const [value, setValue] = React.useState(null);
++ const [key, setKey] = React.useState(null);
++ const listenerSubscription = React.useRef(null);
+
++ React.useEffect(() => {
++ listenerSubscription.current = NativeLocalStorage?.onKeyAdded((pair) => Alert.alert(`New key added: ${pair.key} with value: ${pair.value}`));
+
++ return () => {
++ listenerSubscription.current?.remove();
++ listenerSubscription.current = null;
++ }
++ }, [])
+
+ const [editingValue, setEditingValue] = React.useState<
+ string | null
+ >(null);
+
+- React.useEffect(() => {
+- const storedValue = NativeLocalStorage?.getItem('myKey');
+- setValue(storedValue ?? '');
+- }, []);
+
+ function saveValue() {
++ if (key == null) {
++ Alert.alert('Please enter a key');
++ return;
++ }
+ NativeLocalStorage?.setItem(editingValue ?? EMPTY, key);
+ setValue(editingValue);
+ }
+
+ function clearAll() {
+ NativeLocalStorage?.clear();
+ setValue('');
+ }
+
+ function deleteValue() {
++ if (key == null) {
++ Alert.alert('Please enter a key');
++ return;
++ }
+ NativeLocalStorage?.removeItem(key);
+ setValue('');
+ }
+
++ function retrieveValue() {
++ if (key == null) {
++ Alert.alert('Please enter a key');
++ return;
++ }
++ const val = NativeLocalStorage?.getItem(key);
++ setValue(val);
++ }
+
+ return (
+
+
+ Current stored value is: {value ?? 'No Value'}
+
++ Key:
++
++ Value:
+
+
++
+
+
+
+ );
+}
+
+const styles = StyleSheet.create({
+ text: {
+ margin: 10,
+ fontSize: 20,
+ },
+ textInput: {
+ margin: 10,
+ height: 40,
+ borderColor: 'black',
+ borderWidth: 1,
+ paddingLeft: 5,
+ paddingRight: 5,
+ borderRadius: 5,
+ },
+});
+
+export default App;
+```
+
+There are a few relevant changes to look at:
+
+1. You need to import the `EventSubscription` type from `react-native` to handle the `EventSubscription`
+2. You need to use a `useRef` to keep track of the `EventSubscription` reference
+3. You register the listener using an `useEffect` hook. The `onKeyAdded` function takes a callback with an object of type `KeyValuePair` as a function parameter.
+4. The callback added to `onKeyAdded` is executed every time the event is emitted from Native to JS.
+5. In the `useEffect` cleanup function, you `remove` the event subscription and you set the ref to `null`.
+
+The rest of the changes are regular React changes to improve the App for this new feature.
+
+## Step 4: Write your Native Code
+
+With everything prepared, let's start writing native platform code.
+
+
+
+
+Assuming you followed the guide for iOS described in the [Native Modules guide](/docs/turbo-native-modules-introduction?platforms=android&language=typescript#3-write-application-code-using-the-turbo-native-module), what's left to do is to plug the code that emit the events in your app.
+
+To do so, you have to:
+
+1. Open the `NativeLocalStorage.kt` file
+2. Modify it as it follows:
+
+```diff title="NativeLocalStorage"
+package com.nativelocalstorage
+
+import android.content.Context
+import android.content.SharedPreferences
+import com.nativelocalstorage.NativeLocalStorageSpec
++import com.facebook.react.bridge.Arguments
+import com.facebook.react.bridge.ReactApplicationContext
++import com.facebook.react.bridge.WritableMap
+
+class NativeLocalStorageModule(reactContext: ReactApplicationContext) : NativeLocalStorageSpec(reactContext) {
+
+ override fun getName() = NAME
+
+ override fun setItem(value: String, key: String) {
++ var shouldEmit = false
++ if (getItem(key) != null) {
++ shouldEmit = true
++ }
+ val sharedPref = getReactApplicationContext().getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
+ val editor = sharedPref.edit()
+ editor.putString(key, value)
+ editor.apply()
+
++ if (shouldEmit == true) {
++ val eventData = Arguments.createMap().apply {
++ putString("key", key)
++ putString("value", value)
++ }
++ emitOnKeyAdded(eventData)
++ }
+ }
+
+ override fun getItem(key: String): String? {
+ val sharedPref = getReactApplicationContext().getSharedPreferences("my_prefs", Context.MODE_PRIVATE)
+ val username = sharedPref.getString(key, null)
+ return username.toString()
+ }
+```
+
+First, you need to import a couple of types that you need to use to create the eventData that needs to be sent from Native to JS. These imports are:
+
+- `import com.facebook.react.bridge.Arguments`
+- `import com.facebook.react.bridge.WritableMap`
+
+Secondly, you need to implement the logic that actually emits the event to JS. In case of complex types, like the `KeyValuePair` defined in the specs, Codegen will generate a function that expects a `ReadableMap` as a parameter. You can create the `ReadableMap` by using the `Arguments.createMap()` factory method, and use the `apply` function to populate the map. It's your responsibility to make sure that the the keys you are using in the map are the same properties that are defined in the spec type in JS.
+
+
+
+
+Assuming you followed the guide for iOS described in the [Native Modules guide](/docs/turbo-native-modules-introduction?platforms=ios&language=typescript#3-write-application-code-using-the-turbo-native-module), what's left to do is to plug the code that emit the events in your app.
+
+To do so, you have to:
+
+1. Open the `RCTNativeLocalStorage.h` file.
+2. Change the base class from `NSObject` to `NativeLocalStorageSpecBase`
+
+```diff title="RCTNativeLocalStorage.h"
+#import
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+-@interface RCTNativeLocalStorage : NSObject
++@interface RCTNativeLocalStorage : NativeLocalStorageSpecBase
+
+@end
+
+NS_ASSUME_NONNULL_END
+```
+
+3. Open the `RCTNativeLocalStorage.mm` file.
+4. Modify it to emit the events when needed, for example:
+
+```diff title="RCTNativeLocalStorage.mm"
+ - (void)setItem:(NSString *)value key:(NSString *)key {
++ BOOL shouldEmitEvent = NO;
++ if (![self getItem:key]) {
++ shouldEmitEvent = YES;
++ }
+ [self.localStorage setObject:value forKey:key];
+
++ if (shouldEmitEvent) {
++ [self emitOnKeyAdded:@{@"key": key, @"value": value}];
++ }
+}
+```
+
+The `NativeLocalStorageSpecBase` is a base class that provides the `emitOnKeyAdded` method and its basic implementation and boilerplate. Thanks to this class, you don't have to handle all the conversion between Objective-C and JSI that is required to send the event to JS.
+
+In case of complex types, like the `KeyValuePair` defined in the specs, Codegen will generate a generic dictionary that you can populate on the native side. It's your responsibility to make sure that the the keys you are using in the dictionary are the same properties that are defined in the spec type in JS.
+
+
+
+
+## Step 5: Run Your App
+
+If you now try to run your app, you should see this behavior.
+
+| Android | iOS |
+| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- |
+| | |
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/native-modules-lifecycle.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/native-modules-lifecycle.md
new file mode 100644
index 00000000000..08dbb1cba5a
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/native-modules-lifecycle.md
@@ -0,0 +1,90 @@
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+# Native Modules Lifecycle
+
+In React Native, Native Modules are singleton. The Native Module infrastructure lazily creates a Native Modules the first time it is accessed and it keeps it around whenever the app requires it. This is a performance optimization that allows us to avoid the overhead of creating Native Modules eagerly, at app start, and it ensure faster startup times.
+
+In a pure React Native app, the Native Modules are created once and they are never destroyed. However, in more complex apps, there might be use cases where the Native Modules are destroyed and recreated. Imagine, for example, a brownfield app that mixes some native views with some React Native surfaces, as presented in the [Integrating with Existing App guide](/docs/integration-with-existing-apps). In that case it might make sense to destroy a React Native instance when the user navigates away from a React Native surface and recreate it when the user navigates back to that surface.
+
+When this happens, Native Module that are stateless won't cause any issues. However, for stateful Native Modules it might be necessary to properly invalidate the Native Module to ensure that the state is reset and the resources released.
+
+In this guide, you will explore how to initialize and invalidate a Native Module properly. This guide assumes that you are familiar with how to write a Native Modules and you are comfortable writing native code. If you are not familiar with Native Modules, please read the [Native Modules guide](/docs/next/turbo-native-modules-introduction) first.
+
+## Android
+
+When it comes to Android, all the Native Modules already implements a [TurboModule](https://github.com/facebook/react-native/blob/main/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/interfaces/TurboModule.kt) interface that defines two methods: `initialize()` and `invalidate()`.
+
+The `initialize()` method is called by the Native Module infrastructure when the Native Module is created. This is the best place to put all the initialization code that needs access to the ReactApplicationContext, for example. These are some Native Modules from core that implements the `initialize()` method: [BlobModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/blob/BlobModule.java#L155-L157), [NetworkingModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java#L193-L197).
+
+The `invalidate()` method is called by the Native Module infrastructure when the Native Module is destroyed. This is the best place to put all the cleanup code, resetting the Native Module state and release resources that are no longer needed, such as memory and files. These are some Native Modules from core that implements the `invalidate()` method: [DeviceInfoModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/deviceinfo/DeviceInfoModule.kt#L72-L76), [NetworkModule](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactAndroid/src/main/java/com/facebook/react/modules/network/NetworkingModule.java#L200-L212)
+
+## iOS
+
+On iOS, Native Modules conforms to the [`RCTTurboModule`](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/ReactCommon/react/nativemodule/core/platform/ios/ReactCommon/RCTTurboModule.h#L196-L200) protocol. However, this protocol does not expose the `initialize` and `invalidate` method that are exposed by the Android's `TurboModule` class.
+
+Instead, on iOS, there are two additional protocols: [`RCTInitializing`](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/Base/RCTInitializing.h) and [`RCTInvalidating`](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/Base/RCTInvalidating.h). These protocols are used to define the `initialize` and `invalidate` methods, respectively.
+
+If your module needs to run some initialization code, then you can conform to the `RCTInitializing` protocol and implement the `initialize` method. To do so, you have to:
+
+1. Modify the `NativeModule.h` file by adding the following lines:
+
+```diff title="NativeModule.h"
++ #import
+
+//...
+
+- @interface NativeModule : NSObject
++ @interface NativeModule : NSObject
+//...
+@end
+```
+
+2. Implement the `initialize` method in the `NativeModule.mm` file:
+
+```diff title="NativeModule.mm"
+// ...
+
+@implementation NativeModule
+
++- (void)initialize {
++ // add the initialization code here
++}
+
+@end
+```
+
+These are some Native Modules from core that implements the `initialize` method: [RCTBlobManager](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/Libraries/Blob/RCTBlobManager.mm#L58-L68), [RCTTiming](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/CoreModules/RCTTiming.mm#L121-L124).
+
+If your module needs to run some cleanup code, then you can conform to the `RCTInvalidating` protocol and implement the `invalidate` method. To do so, you have to:
+
+1. Moduify the `NativeModule.h` file by adding the following lines:
+
+```diff title="NativeModule.h"
++ #import
+
+//...
+
+- @interface NativeModule : NSObject
++ @interface NativeModule : NSObject
+
+//...
+
+@end
+```
+
+2. Implement the `invalidate` method in the `NativeModule.mm` file:
+
+```diff title="NativeModule.mm"
+
+// ...
+
+@implementation NativeModule
+
++- (void)invalidate {
++ // add the cleanup code here
++}
+
+@end
+```
+
+These are some Native Modules from core that implements the `invalidate` method: [RCTAppearance](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/CoreModules/RCTAppearance.mm#L151-L155), [RCTDeviceInfo](https://github.com/facebook/react-native/blob/0617accecdcb11159ba15c34885f294bc206aa89/packages/react-native/React/CoreModules/RCTDeviceInfo.mm#L127-L133).
diff --git a/cnwebsite/versioned_docs/version-0.85/the-new-architecture/pure-cxx-modules.md b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/pure-cxx-modules.md
new file mode 100644
index 00000000000..37fa505e53f
--- /dev/null
+++ b/cnwebsite/versioned_docs/version-0.85/the-new-architecture/pure-cxx-modules.md
@@ -0,0 +1,503 @@
+import {getCoreBranchNameForCurrentVersion} from '@site/src/getCoreBranchNameForCurrentVersion';
+import {getCurrentVersion} from '@site/src/getCurrentVersion';
+import CodeBlock from '@theme/CodeBlock';
+
+# Cross-Platform Native Modules (C++)
+
+import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants';
+
+Writing a module in C++ is the best way to share platform-agnostic code between Android and iOS. With pure C++ modules, you can write your logic only once and reuse it right away from all the platforms, without the need of writing platform-specific code.
+
+In this guide, we will go through the creation of a pure C++ Turbo Native Module:
+
+1. Create the JS specs
+2. Configure Codegen to generate the scaffolding
+3. Implement the Native logic
+4. Register the module in the Android and iOS application
+5. Test your changes in JS
+
+The rest of this guide assumes that you have created your application running the command:
+
+
+{`npx @react-native-community/cli@latest init SampleApp --version ${getCurrentVersion()}`}
+
+
+## 1. Create the JS specs
+
+Pure C++ Turbo Native Modules are Turbo Native Modules. They need a specification file (also called spec file) so that Codegen can create the scaffolding code for us. The specification file is also what we use to access the Turbo Native Module in JS.
+
+Spec files need to be written in a typed JS dialect. React Native currently supports Flow or TypeScript.
+
+1. Inside the root folder of your app, create a new folder called `specs`.
+2. Create a new file called `NativeSampleModule.ts` with the following code:
+
+:::warning
+All Native Turbo Module spec files must have the prefix `Native`, otherwise Codegen will ignore them.
+:::
+
+
+
+
+```ts title="specs/NativeSampleModule.ts"
+// @flow
+import type {TurboModule} from 'react-native'
+import { TurboModuleRegistry } from "react-native";
+
+export interface Spec extends TurboModule {
+ +reverseString: (input: string) => string;
+}
+
+export default (TurboModuleRegistry.getEnforcing(
+ "NativeSampleModule"
+): Spec);
+```
+
+
+
+
+```ts title="specs/NativeSampleModule.ts"
+import {TurboModule, TurboModuleRegistry} from 'react-native';
+
+export interface Spec extends TurboModule {
+ readonly reverseString: (input: string) => string;
+}
+
+export default TurboModuleRegistry.getEnforcing(
+ 'NativeSampleModule',
+);
+```
+
+
+
+
+## 2. Configure Codegen
+
+The next step is to configure [Codegen](what-is-codegen.md) in your `package.json`. Update the file to include:
+
+```json title="package.json"
+ "start": "react-native start",
+ "test": "jest"
+ },
+ // highlight-add-start
+ "codegenConfig": {
+ "name": "AppSpecs",
+ "type": "modules",
+ "jsSrcsDir": "specs",
+ "android": {
+ "javaPackageName": "com.sampleapp.specs"
+ }
+ },
+ // highlight-add-end
+ "dependencies": {
+```
+
+This configuration tells Codegen to look for spec files in the `specs` folder. It also instructs Codegen to only generate code for `modules` and to namespace the generated code as `AppSpecs`.
+
+## 3. Write the Native Code
+
+Writing a C++ Turbo Native Module allows you to share the code between Android and iOS. Therefore we will be writing the code once, and we will look into what changes we need to apply to the platforms so that the C++ code can be picked up.
+
+1. Create a folder named `shared` at the same level as the `android` and `ios` folders.
+2. Inside the `shared` folder, create a new file called `NativeSampleModule.h`.
+
+ ```cpp title="shared/NativeSampleModule.h"
+ #pragma once
+
+ #include
+
+ #include
+ #include
+
+ namespace facebook::react {
+
+ class NativeSampleModule : public NativeSampleModuleCxxSpec {
+ public:
+ NativeSampleModule(std::shared_ptr jsInvoker);
+
+ std::string reverseString(jsi::Runtime& rt, std::string input);
+ };
+
+ } // namespace facebook::react
+
+ ```
+
+3. Inside the `shared` folder, create a new file called `NativeSampleModule.cpp`.
+
+ ```cpp title="shared/NativeSampleModule.cpp"
+ #include "NativeSampleModule.h"
+
+ namespace facebook::react {
+
+ NativeSampleModule::NativeSampleModule(std::shared_ptr jsInvoker)
+ : NativeSampleModuleCxxSpec(std::move(jsInvoker)) {}
+
+ std::string NativeSampleModule::reverseString(jsi::Runtime& rt, std::string input) {
+ return std::string(input.rbegin(), input.rend());
+ }
+
+ } // namespace facebook::react
+ ```
+
+Let's have a look at the two files we created:
+
+- The `NativeSampleModule.h` file is the header file for a Pure C++ TurboModule. The `include` statements make sure that we include the specs that will be created by Codegen and that contains the interface and the base class we need to implement.
+- The module lives in the `facebook::react` namespace to have access to all the types that live in that namespace.
+- The class `NativeSampleModule` is the actual Turbo Native Module class and it extends the `NativeSampleModuleCxxSpec` class which contains some glue code and boilerplate code to let this class behave as a Turbo Native Module.
+- Finally, we have the constructor, that accepts a pointer to the `CallInvoker`, to communicate with JS if needed and the function's prototype we have to implement.
+
+The `NativeSampleModule.cpp` file is the actual implementation of our Turbo Native Module and implements the constructor and the method that we declared in the specs.
+
+## 4. Register the Module in the platform
+
+The next steps will let us register the module in the platform. This is the step that exposes the native code to JS so that the React Native application can finally call the native methods from the JS layer.
+
+This is the only time when we will have to write some platform-specific code.
+
+### Android
+
+To make sure that the Android app can effectively build the C++ Turbo Native Module, we need to:
+
+1. Create a `CMakeLists.txt` to access our C++ code.
+2. Modify `build.gradle` to point to the newly created `CMakeLists.txt` file.
+3. Create an `OnLoad.cpp` file in our Android app to register the new Turbo Native Module.
+
+#### 1. Create the `CMakeLists.txt` file
+
+Android uses CMake to build. CMake needs to access the files we defined in our shared folder to be able to build them.
+
+1. Create a new folder `SampleApp/android/app/src/main/jni`. The `jni` folder is where the C++ side of Android lives.
+2. Create a `CMakeLists.txt` file and add this context:
+
+```shell 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 React Native application
+include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)
+
+# Define where the additional source code lives. We need to crawl back the jni, main, src, app, android folders
+target_sources(${CMAKE_PROJECT_NAME} PRIVATE ../../../../../shared/NativeSampleModule.cpp)
+
+# Define where CMake can find the additional header files. We need to crawl back the jni, main, src, app, android folders
+target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC ../../../../../shared)
+```
+
+The CMake file does the following things:
+
+- Defines the `appmodules` library, where all the app C++ code will be included.
+- Loads the base React Native's CMake file.
+- Adds the Module C++ source code that we need to build with the `target_sources` directives. By default React Native will already populate the `appmodules` library with default sources, here we include our custom one. You can see that we need to crawl back from the `jni` folder to the `shared` folder where our C++ Turbo Module lives.
+- Specifies where CMake can find the module header files. Also in this case we need to crawl back from the `jni` folder.
+
+#### 2. Modify `build.gradle` to include the custom C++ code
+
+Gradle is the tool that orchestrates the Android build. We need to tell it where it can find the `CMake` files to build the Turbo Native Module.
+
+1. Open the `SampleApp/android/app/build.gradle` file.
+2. Add the following block into the Gradle file, within the existing `android` block:
+
+```diff title="android/app/build.gradle"
+ buildTypes {
+ debug {
+ signingConfig signingConfigs.debug
+ }
+ release {
+ // Caution! In production, you need to generate your own keystore file.
+ // see https://reactnative.dev/docs/signed-apk-android.
+ signingConfig signingConfigs.debug
+ minifyEnabled enableProguardInReleaseBuilds
+ proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
+ }
+ }
+
++ externalNativeBuild {
++ cmake {
++ path "src/main/jni/CMakeLists.txt"
++ }
++ }
+}
+```
+
+This block tells the Gradle file where to look for the CMake file. The path is relative to the folder where the `build.gradle` file lives, so we need to add the path to the `CMakeLists.txt` files in the `jni` folder.
+
+#### 3. Register the new Turbo Native Module
+
+The final step is to register the new C++ Turbo Native Module in the runtime, so that when JS requires the C++ Turbo Native Module, the app knows where to find it and can return it.
+
+1. From the folder `SampleApp/android/app/src/main/jni`, run the following command:
+
+
+{`curl -O https://raw.githubusercontent.com/facebook/react-native/${getCoreBranchNameForCurrentVersion()}/packages/react-native/ReactAndroid/cmake-utils/default-app-setup/OnLoad.cpp`}
+
+
+2. Then, modify this file as follows:
+
+```diff title="android/app/src/main/jni/OnLoad.cpp"
+#include
+#include
+#include
+#include
+#include
+#include
+
++ // Include the NativeSampleModule header
++ #include
+
+//...
+
+std::shared_ptr cxxModuleProvider(
+ const std::string& name,
+ const std::shared_ptr& jsInvoker) {
+ // Here you can provide your CXX Turbo Modules coming from
+ // either your application or from external libraries. The approach to follow
+ // is similar to the following (for a module called `NativeCxxModuleExample`):
+ //
+ // if (name == NativeCxxModuleExample::kModuleName) {
+ // return std::make_shared(jsInvoker);
+ // }
+
++ // This code registers the module so that when the JS side asks for it, the app can return it
++ if (name == NativeSampleModule::kModuleName) {
++ return std::make_shared(jsInvoker);
++ }
+
+ // And we fallback to the CXX module providers autolinked
+ return autolinking_cxxModuleProvider(name, jsInvoker);
+}
+
+// leave the rest of the file
+```
+
+These steps download the original `OnLoad.cpp` file from React Native, so that we can safely override it to load the C++ Turbo Native Module in the app.
+
+Once we downloaded the file, we can modify it by:
+
+- Including the header file that points to our module
+- Registering the Turbo Native Module so that when JS requires it, the app can return it.
+
+Now, you can run `yarn android` from the project root to see your app building successfully.
+
+### iOS
+
+To make sure that the iOS app can effectively build the C++ Turbo Native Module, we need to:
+
+1. Install pods and run Codegen.
+2. Add the `shared` folder to our iOS project.
+3. Register the C++ Turbo Native Module in the application.
+
+#### 1. Install Pods and Run Codegen.
+
+The first step we need to run is the usual steps we run every time we have to prepare our iOS application. CocoaPods is the tool we use to setup and install React Native dependencies and, as part of the process, it will also run Codegen for us.
+
+```bash
+cd ios
+bundle install
+bundle exec pod install
+```
+
+#### 2. Add the shared folder to the iOS project
+
+This step adds the `shared` folder to the project to make it visible to Xcode.
+
+1. Open the CocoaPods generated Xcode Workspace.
+
+```bash
+cd ios
+open SampleApp.xcworkspace
+```
+
+2. Click on the `SampleApp` project on the left and select `Add files to "Sample App"...`.
+
+
+
+3. Select the `shared` folder and click on `Add`.
+
+
+
+If you did everything right, your project on the left should look like this:
+
+
+
+#### 3. Registering the Cxx Turbo Native Module in your app
+
+To register a pure Cxx Turbo Native Module in your app, you need to:
+
+1. Create a `ModuleProvider` for the Native Module
+2. Configure the `package.json` to associate the JS module name with the ModuleProvider class.
+
+The ModuleProvider is an Objective-C++ that glues together the Pure C++ module with the rest of your iOS App.
+
+##### 3.1 Create the ModuleProvider
+
+1. From Xcode, select the `SampleApp` project and press ⌘ + N to create a new file.
+2. Select the `Cocoa Touch Class` template
+3. Add the name `NativeSampleModuleProvider` (keep the other field as `Subclass of: NSObject` and `Language: Objective-C`)
+4. Click Next to generate the files.
+5. Rename the `NativeSampleModuleProvider.m` to `NativeSampleModuleProvider.mm`. The `mm` extension denotes an Objective-C++ file.
+6. Implement the content of the `NativeSampleModuleProvider.h` with the following:
+
+```objc title="NativeSampleModuleProvider.h"
+
+#import
+#import
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface NativeSampleModuleProvider : NSObject
+
+@end
+
+NS_ASSUME_NONNULL_END
+```
+
+This declares a `NativeSampleModuleProvider` object that conforms to the `RCTModuleProvider` protocol.
+
+7. Implement the content of the `NativeSampleModuleProvider.mm` with the following:
+
+```objc title="NativeSampleModuleProvider.mm"
+
+#import "NativeSampleModuleProvider.h"
+#import
+#import
+#import "NativeSampleModule.h"
+
+@implementation NativeSampleModuleProvider
+
+- (std::shared_ptr)getTurboModule:
+ (const facebook::react::ObjCTurboModule::InitParams &)params
+{
+ return std::make_shared