React Native:使用 redux saga eventChannel 从组件外部化事件监听器

rgo*_*ezz 5 javascript react-native redux-saga

Redux sagaeventChannel是一个非常优雅的解决方案,可以从组件代码外部连接到外部事件,使它们更简洁、更简洁。一个用例可能是对全局应用程序状态变化做出反应,例如应用程序在前台、后台、不活动......

我担心 React Native 的取消订阅过程。在组件内部,componentWillUnmount是执行取消订阅的地方,因此我们有一些 UI 钩子可以保证我们成功移除侦听器。

例如,当我应用以下代码来跟踪 App 状态更改(活动、非活动或后台)时,我是否会面临内存泄漏?

type NextAppState = 'active' | 'inactive' | 'background';

function createAppStateChannel() {
  return eventChannel((emit: (nextState: NextAppState) => mixed) => {
    AppState.addEventListener('change', emit);
    return () => {
      AppState.removeEventListener('change', emit);
    };
  });
}

export function* appStateListenerSaga(): Generator<*, *, *> {
  try {
    const appStateChannel = yield call(createAppStateChannel);
    while (true) {
      const nextAppState: NextAppState = yield take(appStateChannel);
      if (nextAppState === 'active') {
        // Do something, like syncing with server
      }
  } finally {
    if (yield cancelled()) {
      appStateChannel.close();
    }
  } 
}
Run Code Online (Sandbox Code Playgroud)

我正在考虑 JS 上下文因任何原因被杀死的情况。

我担心的是传奇不会被取消(据我所知),不会执行取消订阅,因此本机侦听器将保持注册状态。下次重新打开应用程序时,我们将注册一个重复的事件侦听器,依此类推。

任何人都可以指出这是否安全还是使用 HOC 基本上更好?我也在使用 react-native-navigation 其中有几个 react 根视图(每个屏幕一个),这就是为什么 HOC 不适合这种情况的原因,因为我必须用 HOC 包裹每个父屏幕,如果我有 3 个屏幕推送到堆栈上,在应用程序恢复时,逻辑将执行 3 次。

rgo*_*ezz 2

所以显然这取决于本机模块的实现。

\n\n

如果本机模块只保留一个侦听器并且所有订阅都在 JS 端管理,那么 \xe2\x80\x99 不是问题。

\n\n

但是,如果在本机端处理新的侦听器,则如果 JS 上下文被终止,则 \xe2\x80\x99 将成为问题,因为内存会泄漏。

\n\n

在 JS 端保留订阅的两个模块的示例是AppStateBackHandler。两者都在本机端保留一个全局侦听器,在 JS 端保留多个订阅者,因此两者都可以安全地与 redux-saga 一起使用eventChannel

\n\n

您可以在这里查看源代码AppState作为示例: https: //github.com/facebook/react-native/blob/master/Libraries/AppState/AppState.js

\n\n

我还没有偶然发现一个相反的模块。\n根据经验,只需浏览 github 源代码上的模块即可了解如何管理订阅。

\n