首页 > 解决方案 > JS 根视图在从其父视图中删除后是否总是会接收来自本机的事件?

问题描述

我的(高度简化的)代码如下所示:

// objc
self.currentSwipeUpView = [[RCTRootView alloc]
   initWithBridge:_bridge moduleName:@"PhotoSwipeUpView"
   initialProperties:nil
];
// elsewhere...
[self.currentSwipeUpView removeFromSuperview];
self.currentSwipeUpView = nil;

// js
function PhotoSwipedUpView() {
    return <TextInput style={{flex: 1}} onChangeText={console.warn} />
}
AppRegistry.registerComponent('PhotoSwipeUpView', () => PhotoSwipeUpView)

self.currentSwipeUpView从其超级视图中删除并取消引用。发生这种情况时,JS 线程是否有可能没有收到待处理的 onChangeText 事件?它会导致console.warn与新文本保持一致吗?

我在想象这样一种情况,即在将 RCTRootView 从其父视图中删除并取消引用之后,事件将被发送到 JS 线程。

此外,我很好奇是否可以在从 JS 端从其父视图中删除 RCTRootView 时收到通知。

我正在使用 ARC,并且我没有对self.currentSwipeUpView.

编辑:我有两个 RCTRootViews。只有其中一个会被卸载,另一个会在应用程序的状态下持续存在。它们使用相同的桥接器,因此使用相同的包和 JS 环境。

标签: react-nativereact-native-ios

解决方案


加载/卸载 JS 包

您加载的 js 包绑定到根视图,并且除了在该视图中之外不是持久的。从父视图中删除根视图后,捆绑包也将被卸载。如果根视图被删除和取消引用,文本更改侦听器也应该被删除并且不应触发。

捆绑包中的 JSX 用于最终设置原生元素及其侦听器。JSX 基本上就是脚本。带有 RN 的 JSXTextInput基本上会生成原生的UITextField. 如果 JSX 指定了一个侦听器,则将一个用于文本更改的本地侦听器添加到本地元素实例中。

即使您加载了两个根视图,它们也会彼此独立运行。如果卸载了一个根视图,则与屏幕上的 TextInput 关联的侦听器不应再接收事件。您的第二个根视图应该不受影响,因为它将为 TextInput 设置单独的侦听器。

事件/时间问题

我想完美时机的可能性很小,并且取决于调用 removeFromSuperview 的位置,js 可能会在视图被完全删除和取消引用之前接收到事件,但如果这有可能影响您的应用程序的功能,我建议使用另一种模式与您的数据交互并移除屏幕。

可能的解决方案

如果不知道你想做什么就很难说,但是你可以,例如,使用RCTEventEmitter/发布一个关闭 React Native 视图的通知NativeEventEmitter,然后让 React Native 屏幕使用一个本机函数自行关闭,该函数只是将其从超级视图。这种类型的模式也可以回答您的第二个问题(在某种意义上),因为您实际上是在 RN 屏幕关闭之前告诉它,允许它在被删除之前采取任何必要的操作。


推荐阅读