From d025d4f4b3ee0c2f2f9f72c0cdb0c47f76fef9d4 Mon Sep 17 00:00:00 2001 From: sunnylqm Date: Fri, 17 Apr 2026 12:27:37 +0800 Subject: [PATCH 1/3] docs(cndocs): sync translation updates for 11 docs --- cndocs/alertios.md | 2 +- cndocs/asyncstorage.md | 4 +- cndocs/fabric-native-components-android.md | 82 +++++++++++----------- cndocs/gesture-responder-system.md | 65 +++++++++-------- cndocs/legacy/native-components-android.md | 47 ++++++------- cndocs/legacy/native-modules-intro.md | 24 +++---- cndocs/out-of-tree-platforms.md | 36 +++++----- cndocs/strict-typescript-api.md | 4 +- cndocs/turbo-native-modules-android.md | 4 +- cndocs/using-a-listview.md | 61 +++++++++------- cndocs/using-a-scrollview.md | 20 +++--- 11 files changed, 184 insertions(+), 165 deletions(-) diff --git a/cndocs/alertios.md b/cndocs/alertios.md index 50399425674..831c3fde4d9 100644 --- a/cndocs/alertios.md +++ b/cndocs/alertios.md @@ -1,6 +1,6 @@ --- id: alertios -title: AlertIOS +title: '❌ AlertIOS' --- :::danger 已从 React Native 中移除 diff --git a/cndocs/asyncstorage.md b/cndocs/asyncstorage.md index 1ceb8ced2e8..ae437aebf79 100644 --- a/cndocs/asyncstorage.md +++ b/cndocs/asyncstorage.md @@ -1,8 +1,8 @@ --- id: asyncstorage -title: 🚧 AsyncStorage +title: '❌ AsyncStorage' --- -:::危险已从 React Native 中移除 +:::danger 已从 React Native 中移除 请改用[社区包](https://reactnative.directory/?search=storage)之一。 ::: diff --git a/cndocs/fabric-native-components-android.md b/cndocs/fabric-native-components-android.md index e9f6f455ef2..5f3e47107c7 100644 --- a/cndocs/fabric-native-components-android.md +++ b/cndocs/fabric-native-components-android.md @@ -1,6 +1,6 @@ --- id: fabric-native-components-android -title: 'Fabric 原生 UI 组件:Android' +title: 'Fabric 原生模块:Android' --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; @@ -163,9 +163,9 @@ class ReactWebView: WebView { eventDispatcher?.dispatchEvent(event) } - enum class OnScriptLoadedEventResult() { - success(), - error() + enum class OnScriptLoadedEventResult { + success, + error; } inner class OnScriptLoadedEvent( @@ -190,24 +190,24 @@ class ReactWebView: WebView { 然后,代码定义了一个实际发出事件的帮助函数。要发出事件,你必须: - 获取 `ReactContext` 的引用; -- retrieve the `surfaceId` of the view that you are presenting; -- grab a reference to the `eventDispatcher` associated with the view; -- build the payload for the event using a `WritableMap` object; -- create the event object that you need to send to JavaScript; -- call the `eventDispatcher.dispatchEvent` to send the event. +- 获取当前所呈现视图的 `surfaceId`; +- 获取与该视图关联的 `eventDispatcher` 引用; +- 使用 `WritableMap` 对象构建事件的负载; +- 创建需要发送给 JavaScript 的事件对象; +- 调用 `eventDispatcher.dispatchEvent` 发送事件。 -The last part of the file contains the definition of the data types you need to send the event: +文件的最后一部分包含了发送事件所需的数据类型定义: -- The `OnScriptLoadedEventResult`, with the possible outcomes of the `OnScriptLoaded` event. -- The actual ``OnScriptLoadedEvent` that needs to extend the React Native's `Event` class. +- `OnScriptLoadedEventResult`,表示 `OnScriptLoaded` 事件可能的结果。 +- 实际的 `OnScriptLoadedEvent`,它需要继承 React Native 的 `Event` 类。 -### 3. Write the `WebViewManager` +### 3. 编写 `WebViewManager` -The `WebViewManager` is the class that connects the React Native runtime with the native view. +`WebViewManager` 是将 React Native 运行时与原生视图连接起来的类。 -When React receives the instruction from the app to render a specific component, React uses the registered view manager to create the view and to pass all the required properties. +当 React 收到应用发来的渲染某个组件的指令时,它会使用已注册的 view manager 来创建该视图,并传入所有必需的属性。 -This is the code of the `ReactWebViewManager`. +下面是 `ReactWebViewManager` 的代码。 @@ -327,23 +327,23 @@ class ReactWebViewManager(context: ReactApplicationContext) : SimpleViewManager< -The `ReactWebViewManager` extends the `SimpleViewManager` class from React and implements the `CustomWebViewManagerInterface`, generated by Codegen. +`ReactWebViewManager` 继承了 React 的 `SimpleViewManager` 类,并实现了由 Codegen 生成的 `CustomWebViewManagerInterface`。 -It holds a reference of the `CustomWebViewManagerDelegate`, another element generated by Codegen. +它持有 `CustomWebViewManagerDelegate` 的引用,这也是由 Codegen 生成的另一个对象。 -It then overrides the `getName` function, which must return the same name used in the spec's `codegenNativeComponent` function call. +随后它重写了 `getName` 函数,该函数必须返回与 spec 中 `codegenNativeComponent` 调用所使用名称相同的值。 -The `createViewInstance` function is responsible to instantiate a new `ReactWebView`. +`createViewInstance` 函数负责实例化一个新的 `ReactWebView`。 -Then, the ViewManager needs to define how all the React's compnoents props will update the native view. In the example, you need to decide how to handle the `sourceURL` property that React will set on the `WebView`. +接着,ViewManager 需要定义 React 组件的各个 props 如何更新原生视图。在这个示例中,你需要决定如何处理 React 设置到 `WebView` 上的 `sourceURL` 属性。 -Finally, if the component can emit an event, you need to map the event name by overriding the `getExportedCustomBubblingEventTypeConstants` for bubbling events, or the `getExportedCustomDirectEventTypeConstants` for direct events. +最后,如果组件可以发出事件,你需要通过重写冒泡事件对应的 `getExportedCustomBubblingEventTypeConstants`,或直接事件对应的 `getExportedCustomDirectEventTypeConstants`,来映射事件名称。 -### 4. Write the `ReactWebViewPackage` +### 4. 编写 `ReactWebViewPackage` -As you do with Native Modules, Native Components also need to implement the `ReactPackage` class. This is an object that you can use to register the component in the React Native runtime. +与 Native Modules 类似,Native Components 也需要实现 `ReactPackage` 类。你可以使用这个对象在 React Native 运行时中注册组件。 -This is the code for the `ReactWebViewPackage`: +下面是 `ReactWebViewPackage` 的代码: @@ -351,7 +351,7 @@ This is the code for the `ReactWebViewPackage`: ```java title="Demo/android/src/main/java/com/webview/ReactWebViewPackage.java" package com.webview; -import com.facebook.react.TurboReactPackage; +import com.facebook.react.BaseReactPackage; import com.facebook.react.bridge.NativeModule; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.module.model.ReactModuleInfo; @@ -363,7 +363,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -public class ReactWebViewPackage extends TurboReactPackage { +public class ReactWebViewPackage extends BaseReactPackage { @Override public List> createViewManagers(ReactApplicationContext reactContext) { return Collections.singletonList(new ReactWebViewManager(reactContext)); @@ -381,7 +381,7 @@ public class ReactWebViewPackage extends TurboReactPackage { public ReactModuleInfoProvider getReactModuleInfoProvider() { return new ReactModuleInfoProvider() { @Override - public Map get() { + public Map getReactModuleInfos() { Map map = new HashMap<>(); map.put(ReactWebViewManager.REACT_CLASS, new ReactModuleInfo( ReactWebViewManager.REACT_CLASS, // name @@ -401,17 +401,17 @@ public class ReactWebViewPackage extends TurboReactPackage { -```kotlin title="Demo/android/src/main/java/com/webview/ReactWebView.kt" +```kotlin title="Demo/android/src/main/java/com/webview/ReactWebViewPackage.kt" package com.webview -import com.facebook.react.TurboReactPackage +import com.facebook.react.BaseReactPackage 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.uimanager.ViewManager -class ReactWebViewPackage : TurboReactPackage() { +class ReactWebViewPackage : BaseReactPackage() { override fun createViewManagers(reactContext: ReactApplicationContext): List> { return listOf(ReactWebViewManager(reactContext)) } @@ -425,10 +425,10 @@ class ReactWebViewPackage : TurboReactPackage() { override fun getReactModuleInfoProvider(): ReactModuleInfoProvider = ReactModuleInfoProvider { mapOf(ReactWebViewManager.REACT_CLASS to ReactModuleInfo( - _name = ReactWebViewManager.REACT_CLASS, - _className = ReactWebViewManager.REACT_CLASS, - _canOverrideExistingModule = false, - _needsEagerInit = false, + name = ReactWebViewManager.REACT_CLASS, + className = ReactWebViewManager.REACT_CLASS, + canOverrideExistingModule = false, + needsEagerInit = false, isCxxModule = false, isTurboModule = true, ) @@ -440,15 +440,15 @@ class ReactWebViewPackage : TurboReactPackage() { -The `ReactWebViewPackage` extends the `TurboReactPackage` and implements all the methods required to properly register our component. +`ReactWebViewPackage` 继承了 `BaseReactPackage`,并实现了正确注册组件所需的全部方法。 -- the `createViewManagers` method is the factory method that creates the `ViewManager` that manage the custom views. -- the `getModule` method returns the proper ViewManager depending on the View that React Native needs to render. -- the `getReactModuleInfoProvider` provides all the information required when registering the module in the runtime, +- `createViewManagers` 方法是一个工厂方法,用于创建管理自定义视图的 `ViewManager`。 +- `getModule` 方法会根据 React Native 需要渲染的 View 返回相应的 ViewManager。 +- `getReactModuleInfoProvider` 提供了在运行时注册模块时所需的全部信息。 -### 5. Register the `ReactWebViewPackage` in the application +### 5. 在应用中注册 `ReactWebViewPackage` -Finally, you need to register the `ReactWebViewPackage` in the application. We do that by modifying the `MainApplication` file by adding the `ReactWebViewPackage` to the list of packages returned by the `getPackages` function. +最后,你需要在应用中注册 `ReactWebViewPackage`。具体做法是修改 `MainApplication` 文件,把 `ReactWebViewPackage` 添加到 `getPackages` 函数返回的包列表中。 ```kotlin title="Demo/app/src/main/java/com/demo/MainApplication.kt" package com.demo diff --git a/cndocs/gesture-responder-system.md b/cndocs/gesture-responder-system.md index a6cd3b7bd3c..1ba8e67c06d 100644 --- a/cndocs/gesture-responder-system.md +++ b/cndocs/gesture-responder-system.md @@ -3,61 +3,64 @@ id: gesture-responder-system title: 手势响应系统 --- -移动设备上的手势识别要比在 web 上复杂得多。用户的一次触摸操作的真实意图是什么,App 要经过好几个阶段才能判断。比如 App 需要判断用户的触摸到底是在滚动页面,还是滑动一个 widget,或者只是一个单纯的点击。甚至随着持续时间的不同,这些操作还会转化。此外,还有多点同时触控的情况。 +手势响应系统用于管理应用中手势的生命周期。一次触摸会经历多个阶段,应用会在这个过程中判断用户的意图。例如,应用需要判断这次触摸是在滚动、在某个组件上滑动,还是在点击。而且这种判断在触摸持续期间还可能发生变化。此外,还可能存在多个同时发生的触摸。 -手势响应系统可以使组件在不关心父组件或子组件的前提下自行处理触摸交互。 +触摸响应系统的作用,是让组件在不额外了解其父组件或子组件的前提下,协商如何处理这些触摸交互。 ### 最佳实践 -用户之所以会觉得 web app 和原生 app 在体验上有巨大的差异,触摸响应是一大关键因素。用户的每一个操作都应该具有下列属性: +为了让你的应用拥有更好的体验,每一次交互都应具备以下特性: -反馈/高亮 —— 让用户看到他们到底按到了什么东西,以及松开手后会发生什么。取消功能 —— 当用户正在触摸操作时,应该是可以通过把手指移开来终止操作。这些特性使得用户在使用 App 时体验更好,因为它们可以让用户大胆试用,而不必担心点错了什么。 +- 反馈 / 高亮 —— 告诉用户当前是哪个元素在响应他们的触摸,以及松开手指后会发生什么。 +- 可取消性 —— 当用户正在执行某个操作时,应该能够通过将手指拖离来中止它。 + +这些特性会让用户在使用应用时更加安心,因为它们允许人们大胆尝试和交互,而不必担心误操作。 ### TouchableHighlight 与 Touchable 系列组件 -响应系统用起来可能比较复杂。所以我们提供了一个抽象的`Touchable`实现,用来做“可触控”的组件。这一实现利用了响应系统,使得你可以简单地以声明的方式来配置触控处理。如果要做一个按钮或者网页链接,那么使用`TouchableHighlight`就可以。 +响应系统用起来可能比较复杂。因此,我们为那些需要“可点按”行为的场景提供了一个抽象的 `Touchable` 实现。它基于响应系统,并允许你以声明式的方式配置点击交互。在任何你会在 Web 上使用按钮或链接的地方,都可以使用 `TouchableHighlight`。 ## 响应者的生命周期 一个 View 只要实现了正确的协商方法,就可以成为触摸事件的响应者。我们通过两个方法去“询问”一个 View 是否愿意成为响应者: -* `View.props.onStartShouldSetResponder: (evt) => true,` - 在用户开始触摸的时候(手指刚刚接触屏幕的瞬间),是否愿意成为响应者? -* `View.props.onMoveShouldSetResponder: (evt) => true,` - 如果 View 不是响应者,那么在每一个触摸点开始移动(没有停下也没有离开屏幕)时再询问一次:是否愿意响应触摸交互呢? +- `View.props.onStartShouldSetResponder: evt => true,` - 这个 View 是否希望在触摸开始时成为响应者? +- `View.props.onMoveShouldSetResponder: evt => true,` - 当这个 View 还不是响应者时,每次触摸在其上移动都会调用此函数:这个 View 是否想要“接管”触摸响应? -如果 View 返回 true,并开始尝试成为响应者,那么会触发下列事件之一: +如果 View 返回 true 并尝试成为响应者,则会发生以下情况之一: -* `View.props.onResponderGrant: (evt) => {}` - View 现在要开始响应触摸事件了。这也是需要做高亮的时候,使用户知道他到底点到了哪里。 -* `View.props.onResponderReject: (evt) => {}` - 响应者现在“另有其人”而且暂时不会“放权”,请另作安排。 +- `View.props.onResponderGrant: evt => {}` - 这个 View 现在开始响应触摸事件了。此时通常应该高亮界面,让用户知道发生了什么。 +- `View.props.onResponderReject: evt => {}` - 当前已有别的响应者,并且它不会释放响应权。 -如果 View 已经开始响应触摸事件了,那么下列这些处理函数会被一一调用: +如果 View 正在响应触摸,则可能会调用以下处理函数: -* `View.props.onResponderMove: (evt) => {}` - 用户正在屏幕上移动手指时(没有停下也没有离开屏幕)。 -* `View.props.onResponderRelease: (evt) => {}` - 触摸操作结束时触发,比如"touchUp"(手指抬起离开屏幕)。 -* `View.props.onResponderTerminationRequest: (evt) => true` - 有其他组件请求接替响应者,当前的 View 是否“放权”?返回 true 的话则释放响应者权力。 -* `View.props.onResponderTerminate: (evt) => {}` - 响应者权力已经交出。这可能是由于其他 View 通过`onResponderTerminationRequest`请求的,也可能是由操作系统强制夺权(比如 iOS 上的控制中心或是通知中心)。 +- `View.props.onResponderMove: evt => {}` - 用户正在移动手指。 +- `View.props.onResponderRelease: evt => {}` - 在触摸结束时触发,也就是“touchUp”。 +- `View.props.onResponderTerminationRequest: evt => true` - 有别的元素想要成为响应者。这个 View 是否应该释放响应权?返回 true 表示允许释放。 +- `View.props.onResponderTerminate: evt => {}` - 响应权已从该 View 转移走。可能是在调用 `onResponderTerminationRequest` 之后被其他 View 接管,也可能是在未询问的情况下被操作系统接管(例如 iOS 上打开控制中心或通知中心时)。 -`evt`是一个合成事件,它包含以下结构: +`evt` 是一个合成触摸事件,结构如下: -* `nativeEvent` - * `changedTouches` - 在上一次事件之后,所有发生变化的触摸事件的数组集合(即上一次事件后,所有移动过的触摸点) - * `identifier` - 触摸点的 ID - * `locationX` - 触摸点相对于当前元素的横坐标 - * `locationY` - 触摸点相对于当前元素的纵坐标 - * `pageX` - 触摸点相对于根元素的横坐标 - * `pageY` - 触摸点相对于根元素的纵坐标 - * `target` - 触摸点所在的元素 ID - * `timestamp` - 触摸事件的时间戳,可用于移动速度的计算 - * `touches` - 当前屏幕上的所有触摸点的集合 +- `nativeEvent` + - `changedTouches` - 自上一次事件以来发生变化的所有触摸事件数组 + - `identifier` - 触摸点的 ID + - `locationX` - 触摸点相对于当前元素的 X 坐标 + - `locationY` - 触摸点相对于当前元素的 Y 坐标 + - `pageX` - 触摸点相对于根元素的 X 坐标 + - `pageY` - 触摸点相对于根元素的 Y 坐标 + - `target` - 接收触摸事件的元素节点 ID + - `timestamp` - 触摸时间标识,可用于速度计算 + - `touches` - 当前屏幕上的所有触摸点数组 ### 捕获 ShouldSet 事件处理 -`onStartShouldSetResponder`与`onMoveShouldSetResponder`是以冒泡的形式调用的,即嵌套最深的节点最先调用。这意味着当多个 View 同时在`*ShouldSetResponder`中返回 true 时,最底层的 View 将优先“夺权”。在多数情况下这并没有什么问题,因为这样可以确保所有控件和按钮是可用的。 +`onStartShouldSetResponder` 和 `onMoveShouldSetResponder` 采用冒泡顺序调用,最深层的节点会最先收到调用。这意味着当多个 View 在 `*ShouldSetResponder` 处理函数中都返回 true 时,最深层的组件会成为响应者。在大多数场景下,这正是我们想要的效果,因为它能确保所有控件和按钮都可用。 -但是有些时候,某个父 View 会希望能先成为响应者。我们可以利用“捕获期”来解决这一需求。响应系统在从最底层的组件开始冒泡之前,会首先执行一个“捕获期”,在此期间会触发`on*ShouldSetResponderCapture`系列事件。因此,如果某个父 View 想要在触摸操作开始时阻止子组件成为响应者,那就应该处理`onStartShouldSetResponderCapture`事件并返回 true 值。 +但有时父级组件会希望确保自己成为响应者。这时可以使用捕获阶段。在响应系统从最深层组件开始冒泡之前,会先执行一次捕获阶段,并触发 `on*ShouldSetResponderCapture`。因此,如果父级 View 想在触摸开始时阻止子组件成为响应者,它就应该在 `onStartShouldSetResponderCapture` 处理函数中返回 true。 -* `View.props.onStartShouldSetResponderCapture: (evt) => true,` -* `View.props.onMoveShouldSetResponderCapture: (evt) => true,` +- `View.props.onStartShouldSetResponderCapture: evt => true,` +- `View.props.onMoveShouldSetResponderCapture: evt => true,` ### PanResponder -要使用更高级的手势功能,请参看[PanResponder](panresponder.md). +如果你需要更高层级的手势解释能力,请参阅 [PanResponder](panresponder.md)。 diff --git a/cndocs/legacy/native-components-android.md b/cndocs/legacy/native-components-android.md index f2cc905a131..7cc2fb3c1ee 100644 --- a/cndocs/legacy/native-components-android.md +++ b/cndocs/legacy/native-components-android.md @@ -32,7 +32,7 @@ import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecat 4. 把这个视图管理类注册到应用程序包的`createViewManagers`里。 5. 实现 JavaScript 模块。 -## 1. 创建`ViewManager`的子类 +### 1. 创建`ViewManager`的子类 在这个例子里我们创建一个视图管理类`ReactImageManager`,它继承自`SimpleViewManager`。`ReactImageView`是这个视图管理类所管理的对象类型,也就是我们自定义的原生视图。`getName`方法返回的名字会用于在 JavaScript 端引用。 @@ -75,7 +75,7 @@ public class ReactImageManager extends SimpleViewManager { -## 2. 实现方法`createViewInstance` +### 2. 实现方法`createViewInstance` 视图在`createViewInstance`中创建,且应当把自己初始化为默认的状态。所有属性的设置都通过后续的`updateView`来进行。 @@ -100,9 +100,7 @@ public class ReactImageManager extends SimpleViewManager { -## 3. 通过`@ReactProp`(或`@ReactPropGroup`)注解来导出属性的设置方法。 - - +### 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`. @@ -157,7 +155,7 @@ public class ReactImageManager extends SimpleViewManager { -## 4. 注册`ViewManager` +### 4. 注册`ViewManager` 最后一步就是把视图控制器注册到应用中。这和[原生模块](native-modules-android.md)的注册方法类似,唯一的区别是我们把它放到`createViewManagers`方法的返回值里。 @@ -188,12 +186,12 @@ public class ReactImageManager extends SimpleViewManager { 完成上面这些代码后,请一定记得要重新编译!(运行`yarn android`命令) -## 5. 实现对应的 JavaScript 模块 +### 5. 实现对应的 JavaScript 模块 整个过程的最后一步就是创建 JavaScript 模块并且定义 Java 和 JavaScript 之间的接口层。我们建议你使用 TypeScript 来规范定义接口的具体结构,或者至少用注释说明清楚(老版本的 RN 使用`propTypes`来规范接口定义,这一做法已不再支持)。 ```tsx title="ImageView.tsx" -import { requireNativeComponent } from 'react-native'; +import {requireNativeComponent} from 'react-native'; /** * Composes `View`. @@ -207,7 +205,7 @@ export default requireNativeComponent('RCTImageView'); `requireNativeComponent`目前只接受一个参数,即原生视图的名字。如果你还需要做一些复杂的逻辑譬如事件处理,那么可以把原生组件用一个普通 React 组件封装。后文的`MyCustomView`例子里演示了这种用法。 -# 事件 +## 事件 现在我们已经知道了怎么导出一个原生视图组件,并且我们可以在 JS 里很方便的控制它了。不过我们怎么才能处理来自用户的事件,譬如缩放操作或者拖动?当一个原生事件发生的时候,它应该也能触发 JavaScript 端视图上的事件,这两个视图会依据`getId()`而关联在一起。 @@ -293,29 +291,26 @@ public class ReactImageManager extends SimpleViewManager { 这个回调会传递一个原生事件对象,一般来说我们会在封装组件里进行处理以便外部使用: ```tsx title="MyCustomView.tsx" -import React, { useCallback } from 'react'; +import React, {useCallback} from 'react'; -const MyCustomView = ({ onChangeMessage, ...props }) => { - const onChange = useCallback((event) => { - if (!onChangeMessage) { - return; - } - onChangeMessage(event.nativeEvent.message); - }, [onChangeMessage]); - - return ( - +const MyCustomView = ({onChangeMessage, ...props}) => { + const onChange = useCallback( + event => { + if (!onChangeMessage) { + return; + } + onChangeMessage(event.nativeEvent.message); + }, + [onChangeMessage], ); -}; + return ; +}; const RCTMyCustomView = requireNativeComponent(`RCTMyCustomView`); ``` -# 与 Android Fragment 的整合实例 +## 与 Android Fragment 的整合实例 为了将现有的原生 UI 元素整合到 React Native 应用中,你可能需要使用 Android Fragments 来对本地组件进行更精细的控制,而不是从 `ViewManager` 返回一个 `View`。如果你想在[生命周期方法](https://developer.android.com/guide/fragments/lifecycle)的帮助下添加与视图绑定的自定义逻辑,如`onViewCreated`、`onPause`、`onResume`,你会用得到它。下面的步骤将告诉你如何做到这一点: @@ -827,7 +822,7 @@ protected List getPackages() { I. `MyViewManager.tsx` ```tsx title="MyViewManager.tsx" -import { requireNativeComponent } from 'react-native'; +import {requireNativeComponent} from 'react-native'; export const MyViewManager = requireNativeComponent('MyViewManager'); ``` diff --git a/cndocs/legacy/native-modules-intro.md b/cndocs/legacy/native-modules-intro.md index 4d3f10bd3df..4e14ba9dfca 100644 --- a/cndocs/legacy/native-modules-intro.md +++ b/cndocs/legacy/native-modules-intro.md @@ -7,24 +7,24 @@ import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecat -有时候 App 需要访问平台 API,但 React Native 可能还没有相应的模块包装;或者你需要复用一些 Java 代码,而不是用 Javascript 重新实现一遍;又或者你需要实现某些高性能的、多线程的代码,譬如图片处理、数据库、或者各种高级扩展等等。 +有时 React Native 应用需要访问 JavaScript 默认未提供的原生平台 API,例如访问 Apple Pay 或 Google Pay 的原生 API。或者你可能希望复用现有的 Objective-C、Swift、Java 或 C++ 库,而不是用 JavaScript 重新实现它们;又或者你需要编写一些高性能、多线程的代码来处理图片等任务。 -我们把 React Native 设计为可以在其基础上编写真正的原生代码,并且可以访问平台所有的能力。这是一个相对高级的特性,我们并不认为它应当在日常开发的过程中经常出现,但具备这样的能力是很重要的。如果 React Native 还不支持某个你需要的原生特性,你应当可以自己实现该特性的封装。 +NativeModule 系统会将 Java/Objective-C/C++(原生)类的实例以 JavaScript(JS)对象的形式暴露给 JS,这样你就可以在 JS 中执行任意原生代码。虽然我们并不期望这会成为日常开发流程的一部分,但具备这种能力是非常重要的。如果 React Native 没有导出你的 JS 应用所需的某个原生 API,你应该能够自己把它导出来。 -## 创建原生模块 +## 原生模块的设置方式 -有多种方法可以为您的 React Native 应用程序编写原生模块: +为 React Native 应用编写原生模块有几种不同方式: -1. 创建一个可在您的 React Native 应用程序中导入的原生库。阅读[创建原生库](local-library-setup)指南以了解更多信息。 -2. 直接在您的 React Native 应用程序的 iOS / Android 项目中 -3. 作为一个 NPM 包,可以被您/其他 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 应用内部实现一个原生模块。不过,接下来指南中构建出的原生模块也可以作为 NPM 包分发。如果你对此感兴趣,请参阅[将原生模块设置为 NPM 包](native-modules-setup)指南。 -## 教程 +## 开始上手 -在接下来的部分中,我们将带您了解如何在 React Native 应用程序内直接构建一个原生模块的指南。作为一个先决条件,您需要一个 React Native 应用程序来工作。如果您还没有,可以按照[这里](getting-started)的步骤设置一个 React Native 应用程序。 +在接下来的章节中,我们会带你一步步在 React Native 应用内部直接构建一个原生模块。前提是你需要先有一个 React Native 应用可供操作。如果你还没有,可以按照[这里](../getting-started)的步骤先创建一个 React Native 应用。 -想象一下,您想在 React Native 应用程序内的 JavaScript 中访问 iOS/Android 原生日历 API,以创建日历事件。React Native 没有公开与原生日历库通信的 JavaScript API。然而,通过原生模块,您可以编写与原生日历 API 通信的原生代码。然后您可以在 React Native 应用程序中的 JavaScript 里调用该原生代码。 +假设你想在 React Native 应用的 JavaScript 中访问 iOS/Android 的原生日历 API,以创建日历事件。React Native 并没有暴露一个可直接与原生日历库通信的 JavaScript API。不过,通过原生模块,你可以编写与原生日历 API 通信的原生代码,然后在 React Native 应用的 JavaScript 中调用它。 -在接下来的部分中,您将为[Android](native-modules-android)和[iOS](native-modules-ios)创建这样一个 Calendar 原生模块。 +在接下来的章节中,你将分别为 [Android](native-modules-android) 和 [iOS](native-modules-ios) 创建这样一个 Calendar 原生模块。 diff --git a/cndocs/out-of-tree-platforms.md b/cndocs/out-of-tree-platforms.md index 5741ee682b7..c08b4f21a64 100644 --- a/cndocs/out-of-tree-platforms.md +++ b/cndocs/out-of-tree-platforms.md @@ -3,31 +3,35 @@ id: out-of-tree-platforms title: 多平台支持 --- -React Native不仅适用于 Android 和 iOS - 还有社区支持的项目将其应用于其他平台,例如: +React Native 不仅适用于 Android 和 iOS 设备——我们的合作伙伴和社区还维护着一些将 React Native 带到其他平台的项目,例如: -- [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 macOS](https://github.com/microsoft/react-native-macos) - 面向 macOS 和 Cocoa 的 React Native。 +- [React Native Windows](https://github.com/microsoft/react-native-windows) - 面向 Microsoft Universal Windows Platform (UWP) 的 React Native。 +- [React Native visionOS](https://github.com/callstack/react-native-visionos) - 面向 Apple visionOS 的 React Native。 + +**社区项目** + +- [React Native tvOS](https://github.com/react-native-tvos/react-native-tvos) - 面向 Apple TV 和 Android TV 设备的 React Native。 +- [React Native Web](https://github.com/necolas/react-native-web) - 基于 React DOM 在 Web 上运行 React Native。 +- [React Native Skia](https://github.com/react-native-skia/react-native-skia) - 使用 [Skia](https://skia.org/) 作为渲染器的 React Native。目前支持 Linux 和 macOS。 ## 创建你自己的 React Native 平台 -目前,从头开始创建 React Native 平台的过程并没有很好的记录——即将到来的全新架构([Fabric](https://facebook.github.io/react-native/blog/2018/06/14/state-of-react-native-2018))的目标之一是使平台的维护更容易。 +目前,从零开始创建一个 React Native 平台的过程还没有非常完善的文档——即将到来的重新架构([Fabric](/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 文件。 +从 React Native 0.57 开始,你现在可以通过 React Native 的 JavaScript 打包器 [Metro](https://metrobundler.dev/) 注册你的 React Native 平台。这意味着你可以向 `npx react-native bundle` 传递 `--platform example`,它就会查找带有 `.example.js` 后缀的 JavaScript 文件。 -要将你的平台注册到 RNPM,模块名称必须与以下模式之一匹配: +要将你的平台注册到 RNPM,模块名称必须匹配以下模式之一: -- `react-native-example` - 它会搜索所有以`react-native-`开头的顶级模块 -- `@org/react-native-example` - 它会在所有范围内搜索以`react-native-`开头的模块 -- `@react-native-example/module` - 它会在名称以`@react-native-`开头的范围内搜索所有模块 +- `react-native-example` - 它会搜索所有以 `react-native-` 开头的顶级模块 +- `@org/react-native-example` - 它会搜索任意 scope 下以 `react-native-` 开头的模块 +- `@react-native-example/module` - 它会搜索所有位于名称以 `@react-native-` 开头的 scope 下的模块 -你还必须在`package.json`中设置一些内容,如下所示: +你还需要在 `package.json` 中添加如下配置: ```json { @@ -40,4 +44,4 @@ React Native不仅适用于 Android 和 iOS - 还有社区支持的项目将其 } ``` -`"providesModuleNodeModules"`是一组将被添加到 Haste 模块搜索路径的模块,`"platforms"`则是一组将作为有效平台添加的平台后缀。 +`"providesModuleNodeModules"` 是一个数组,其中的模块会被加入 Haste 模块搜索路径;`"platforms"` 也是一个数组,其中的平台后缀会被添加为有效平台。 diff --git a/cndocs/strict-typescript-api.md b/cndocs/strict-typescript-api.md index 20a541b82d1..3c5750fadac 100644 --- a/cndocs/strict-typescript-api.md +++ b/cndocs/strict-typescript-api.md @@ -3,6 +3,8 @@ id: strict-typescript-api title: 严格 TypeScript API(可选加入) --- +import RNRepoLink from '@site/core/RNRepoLink'; + 严格 TypeScript API 是我们未来稳定的 React Native JavaScript API 的预览版。 具体来说,这是 `react-native` npm 包的一套新的 TypeScript 类型,从 0.80 版本开始提供。这些类型提供了更强大、更面向未来的类型准确性,并将允许我们自信地将 React Native 的 API 演进为稳定的形状。选择加入严格 TypeScript API 会带来一些结构性类型差异,因此这是一次性的破坏性更改。 @@ -178,7 +180,7 @@ Animated 节点之前是基于其插值输出的泛型类型。现在,它们 ### 移除一些已废弃的类型 -[`DeprecatedPropertiesAlias.d.ts`](https://github.com/facebook/react-native/blob/0.80-stable/packages/react-native/types/public/DeprecatedPropertiesAlias.d.ts) 中列出的所有类型在严格 API 下都无法访问。 +`DeprecatedPropertiesAlias.d.ts` 中列出的所有类型在严格 API 下都无法访问。 ### 移除剩余的组件属性 diff --git a/cndocs/turbo-native-modules-android.md b/cndocs/turbo-native-modules-android.md index ae28933e974..8cb3ebe4670 100644 --- a/cndocs/turbo-native-modules-android.md +++ b/cndocs/turbo-native-modules-android.md @@ -354,6 +354,6 @@ yarn run android diff --git a/cndocs/using-a-listview.md b/cndocs/using-a-listview.md index c204c52a6a6..f85a3bbbb6f 100644 --- a/cndocs/using-a-listview.md +++ b/cndocs/using-a-listview.md @@ -15,12 +15,12 @@ React Native 提供了几个适用于展示长列表数据的组件,一般而 ```SnackPlayer name=FlatList%20Basics import React from 'react'; -import { FlatList, StyleSheet, Text, View } from 'react-native'; +import {FlatList, StyleSheet, Text, View} from 'react-native'; const styles = StyleSheet.create({ container: { - flex: 1, - paddingTop: 22 + flex: 1, + paddingTop: 22, }, item: { padding: 10, @@ -49,21 +49,21 @@ const FlatListBasics = () => { /> ); -} +}; export default FlatListBasics; ``` -如果要渲染的是一组需要分组的数据,也许还带有分组标签的,那么`SectionList`将是个不错的选择 +如果要渲染的是一组需要分组的数据,也许还带有分组标签的,那么 [SectionList](sectionlist.md) 将是个不错的选择。 ```SnackPlayer name=SectionList%20Basics import React from 'react'; -import { SectionList, StyleSheet, Text, View } from 'react-native'; +import {SectionList, StyleSheet, Text, View} from 'react-native'; const styles = StyleSheet.create({ container: { - flex: 1, - paddingTop: 22 + flex: 1, + paddingTop: 22, }, sectionHeader: { paddingTop: 2, @@ -79,25 +79,38 @@ const styles = StyleSheet.create({ fontSize: 18, height: 44, }, -}) +}); const SectionListBasics = () => { - return ( - - {item}} - renderSectionHeader={({section}) => {section.title}} - keyExtractor={(item, index) => index} - /> - - ); -} + return ( + + {item}} + renderSectionHeader={({section}) => ( + {section.title} + )} + keyExtractor={item => `basicListEntry-${item}`} + /> + + ); +}; export default SectionListBasics; ``` -列表的一个常用场景就是从服务器端取回列表数据然后显示,要实现这一过程,你可能还需要学习[React Native 的网络相关用法](network.md). +列表的一个常用场景就是从服务器端取回列表数据然后显示。要实现这一过程,你可能还需要学习 [React Native 的网络相关用法](network.md)。 diff --git a/cndocs/using-a-scrollview.md b/cndocs/using-a-scrollview.md index e418382d92b..d304274a555 100644 --- a/cndocs/using-a-scrollview.md +++ b/cndocs/using-a-scrollview.md @@ -9,49 +9,51 @@ title: 使用滚动视图 ```SnackPlayer name=Using%20ScrollView import React from 'react'; -import { Image, ScrollView, Text } from 'react-native'; +import {Image, ScrollView, Text} from 'react-native'; const logo = { uri: 'https://reactnative.dev/img/tiny_logo.png', width: 64, - height: 64 + height: 64, }; -export default App = () => ( +const App = () => ( - Scroll me plz + Scroll me plz - If you like + If you like - Scrolling down + Scrolling down - What's the best + What's the best - Framework around? + Framework around? - React Native + React Native ); + +export default App; ``` ScrollViews 可以通过使用`pagingEnabled`属性来允许使用滑动手势对视图进行分页,在 Android 上也可以利用[ViewPager](https://github.com/react-native-community/react-native-viewpager)组件水平滑动视图。 From 0163d476808400ac22c33b00c79609fee7067652 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 13:10:34 +0000 Subject: [PATCH 2/3] fix: apply CodeRabbit auto-fixes Fixed 3 file(s) based on 4 unresolved review comments. Co-authored-by: CodeRabbit --- cndocs/fabric-native-components-android.md | 4 ++-- cndocs/legacy/native-components-android.md | 3 ++- cndocs/out-of-tree-platforms.md | 6 +++--- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cndocs/fabric-native-components-android.md b/cndocs/fabric-native-components-android.md index 5f3e47107c7..55f7393f515 100644 --- a/cndocs/fabric-native-components-android.md +++ b/cndocs/fabric-native-components-android.md @@ -1,6 +1,6 @@ --- id: fabric-native-components-android -title: 'Fabric 原生模块:Android' +title: 'Fabric 原生组件:Android' --- import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem'; import constants from '@site/core/TabsConstants'; @@ -497,4 +497,4 @@ class MainApplication : Application(), ReactApplication { } } -``` +``` \ No newline at end of file diff --git a/cndocs/legacy/native-components-android.md b/cndocs/legacy/native-components-android.md index 7cc2fb3c1ee..22ab6b1dbb8 100644 --- a/cndocs/legacy/native-components-android.md +++ b/cndocs/legacy/native-components-android.md @@ -292,6 +292,7 @@ public class ReactImageManager extends SimpleViewManager { ```tsx title="MyCustomView.tsx" import React, {useCallback} from 'react'; +import {requireNativeComponent} from 'react-native'; const MyCustomView = ({onChangeMessage, ...props}) => { const onChange = useCallback( @@ -862,4 +863,4 @@ export const MyView = ({ style }) => { }; ``` -如果您想使用公开属性设置器 `@ReactProp` (or `@ReactPropGroup`) 详见上面的 [ImageView 示例](#imageview-example)。 +如果您想使用公开属性设置器 `@ReactProp` (or `@ReactPropGroup`) 详见上面的 [ImageView 示例](#imageview-example)。 \ No newline at end of file diff --git a/cndocs/out-of-tree-platforms.md b/cndocs/out-of-tree-platforms.md index c08b4f21a64..9e66e4b91d4 100644 --- a/cndocs/out-of-tree-platforms.md +++ b/cndocs/out-of-tree-platforms.md @@ -19,11 +19,11 @@ React Native 不仅适用于 Android 和 iOS 设备——我们的合作伙伴 ## 创建你自己的 React Native 平台 -目前,从零开始创建一个 React Native 平台的过程还没有非常完善的文档——即将到来的重新架构([Fabric](/blog/2018/06/14/state-of-react-native-2018))的目标之一,就是让平台维护变得更容易。 +目前,从零开始创建一个 React Native 平台的过程还没有非常完善的文档——新的架构([Fabric](/blog/2018/06/14/state-of-react-native-2018))旨在让平台维护更容易。 ### 打包 -从 React Native 0.57 开始,你现在可以通过 React Native 的 JavaScript 打包器 [Metro](https://metrobundler.dev/) 注册你的 React Native 平台。这意味着你可以向 `npx react-native bundle` 传递 `--platform example`,它就会查找带有 `.example.js` 后缀的 JavaScript 文件。 +自 React Native 0.57 起已支持通过 [Metro](https://metrobundler.dev/) 注册自定义平台。这意味着你可以向 `npx react-native bundle` 传递 `--platform example`,它就会查找带有 `.example.js` 后缀的 JavaScript 文件。 要将你的平台注册到 RNPM,模块名称必须匹配以下模式之一: @@ -44,4 +44,4 @@ React Native 不仅适用于 Android 和 iOS 设备——我们的合作伙伴 } ``` -`"providesModuleNodeModules"` 是一个数组,其中的模块会被加入 Haste 模块搜索路径;`"platforms"` 也是一个数组,其中的平台后缀会被添加为有效平台。 +`"providesModuleNodeModules"` 是一个数组,其中的模块会被加入 Haste 模块搜索路径;`"platforms"` 也是一个数组,其中的平台后缀会被添加为有效平台。 \ No newline at end of file From 1a3231684ea5f37e77dac42f1db5a4b9e80696e5 Mon Sep 17 00:00:00 2001 From: "coderabbitai[bot]" <136622811+coderabbitai[bot]@users.noreply.github.com> Date: Sat, 18 Apr 2026 07:27:23 +0000 Subject: [PATCH 3/3] fix: apply CodeRabbit auto-fixes Fixed 2 file(s) based on 1 unresolved review comment. Co-authored-by: CodeRabbit --- cndocs/legacy/native-components-android.md | 2 +- yarn.lock | 29 +++++++++++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/cndocs/legacy/native-components-android.md b/cndocs/legacy/native-components-android.md index 22ab6b1dbb8..19336021670 100644 --- a/cndocs/legacy/native-components-android.md +++ b/cndocs/legacy/native-components-android.md @@ -16,7 +16,7 @@ import NativeDeprecated from '../the-new-architecture/\_markdown_native_deprecat 您还可以通过一个命令来配置生成包含原生组件的本地库模板。阅读[本地库设置](local-library-setup)指南以获取更多详细信息。 ::: -## ImageView 示例 +## ImageView 示例 {#imageview-example} 在这个例子里,我们来看看为了让 JavaScript 中可以使用 ImageView,需要做哪些准备工作。 diff --git a/yarn.lock b/yarn.lock index 79322344deb..93e1a7cbd8f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4433,7 +4433,7 @@ "@types/history" "^4.7.11" "@types/react" "*" -"@types/react@*", "@types/react@^19.2.14": +"@types/react@*", "@types/react@^19.1.17", "@types/react@^19.2.14": version "19.2.14" resolved "https://registry.yarnpkg.com/@types/react/-/react-19.2.14.tgz#39604929b5e3957e3a6fa0001dafb17c7af70bad" integrity sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w== @@ -7165,7 +7165,7 @@ eslint-visitor-keys@^5.0.0: resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz#9e3c9489697824d2d4ce3a8ad12628f91e9f59be" integrity sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA== -eslint@^9.39.3: +eslint@^9.39.2, eslint@^9.39.3: version "9.39.4" resolved "https://registry.yarnpkg.com/eslint/-/eslint-9.39.4.tgz#855da1b2e2ad66dc5991195f35e262bcec8117b5" integrity sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ== @@ -7914,7 +7914,7 @@ glob@^11.0.1: package-json-from-dist "^1.0.0" path-scurry "^2.0.0" -glob@^13.0.6: +glob@^13.0.0, glob@^13.0.6: version "13.0.6" resolved "https://registry.yarnpkg.com/glob/-/glob-13.0.6.tgz#078666566a425147ccacfbd2e332deb66a2be71d" integrity sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw== @@ -8793,7 +8793,7 @@ image-size@^2.0.2: resolved "https://registry.yarnpkg.com/image-size/-/image-size-2.0.2.tgz#84a7b43704db5736f364bf0d1b029821299b4bdc" integrity sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w== -immutable@^5.1.5: +immutable@^5.0.2: version "5.1.5" resolved "https://registry.yarnpkg.com/immutable/-/immutable-5.1.5.tgz#93ee4db5c2a9ab42a4a783069f3c5d8847d40165" integrity sha512-t7xcm2siw+hlUM68I+UEOK+z84RzmN59as9DZ7P1l0994DKUWV7UXBMQZVxaoMSRQ+PBZbHCOoBt7a2wxOMt+A== @@ -13255,6 +13255,11 @@ prettier-linter-helpers@^1.0.1: dependencies: fast-diff "^1.1.2" +prettier@^3.7.4: + version "3.8.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.3.tgz#560f2de55bf01b4c0503bc629d5df99b9a1d09b0" + integrity sha512-7igPTM53cGHMW8xWuVTydi2KO233VFiTNyF5hLJqpilHfmn8C8gPf+PS7dUT64YcXFbiMGZxS9pCSxL/Dxm/Jw== + prettier@^3.8.1: version "3.8.1" resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.8.1.tgz#edf48977cf991558f4fcbd8a3ba6015ba2a3a173" @@ -13511,7 +13516,7 @@ react-devtools-core@^6.1.5: shell-quote "^1.6.1" ws "^7" -react-dom@^19.2.4: +react-dom@^19.1.2: version "19.2.5" resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.2.5.tgz#b8768b10837d0b8e9ca5b9e2d58dff3d880ea25e" integrity sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag== @@ -13656,7 +13661,7 @@ react-router@5.3.4, react-router@^5.3.4: tiny-invariant "^1.0.2" tiny-warning "^1.0.0" -react@^19.2.4: +react@^19.1.2, react@^19.2.4: version "19.2.5" resolved "https://registry.yarnpkg.com/react/-/react-19.2.5.tgz#c888ab8b8ef33e2597fae8bdb2d77edbdb42858b" integrity sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA== @@ -14359,13 +14364,13 @@ sass-loader@^16.0.2: dependencies: neo-async "^2.6.2" -sass@1.98.0: - version "1.98.0" - resolved "https://registry.yarnpkg.com/sass/-/sass-1.98.0.tgz#924ce85a3745ccaccd976262fdc1bc0c13aa8e57" - integrity sha512-+4N/u9dZ4PrgzGgPlKnaaRQx64RO0JBKs9sDhQ2pLgN6JQZ25uPQZKQYaBJU48Kd5BxgXoJ4e09Dq7nMcOUW3A== +sass@1.97.1: + version "1.97.1" + resolved "https://registry.yarnpkg.com/sass/-/sass-1.97.1.tgz#f36e492baf8ccdd08d591b58d3d8b53ea35ab905" + integrity sha512-uf6HoO8fy6ClsrShvMgaKUn14f2EHQLQRtpsZZLeU/Mv0Q1K5P0+x2uvH6Cub39TVVbWNSrraUhDAoFph6vh0A== dependencies: chokidar "^4.0.0" - immutable "^5.1.5" + immutable "^5.0.2" source-map-js ">=0.6.2 <2.0.0" optionalDependencies: "@parcel/watcher" "^2.4.1" @@ -16785,4 +16790,4 @@ yocto-queue@^1.0.0, yocto-queue@^1.1.1: zwitch@^2.0.0, zwitch@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/zwitch/-/zwitch-2.0.4.tgz#c827d4b0acb76fc3e685a4c6ec2902d51070e9d7" - integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== + integrity sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A== \ No newline at end of file