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

Javascript React Native:使用redux saga eventChannel从组件外部化事件侦听器,javascript,react-native,redux-saga,Javascript,React Native,Redux Saga,Redux sagaeventChannel是一个非常优雅的解决方案,可以从组件代码外部连接到外部事件,使它们更简洁。一个用例可以是对全局应用程序状态变化做出反应,比如前台、后台、非活动的应用程序 我很担心取消订阅的过程。 在组件内部,componentWillUnmount是执行您的un订阅的地方,因此我们有一些UI挂钩,可以保证成功删除侦听器 例如,当我应用下面的代码时,为了跟踪应用程序状态的变化(活动、非活动或背景),我会暴露在内存泄漏中吗 type NextAppState = 'act

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

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

例如,当我应用下面的代码时,为了跟踪应用程序状态的变化(活动、非活动或背景),我会暴露在内存泄漏中吗

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();
    }
  } 
}
type nextapstate='active'|'inactive'|'background';
函数createAppStateChannel(){
返回eventChannel((emit:(nextState:nextapstate)=>mixed)=>{
AppState.addEventListener('change',emit);
return()=>{
AppState.removeEventListener('change',emit);
};
});
}
导出函数*appStateListenerSaga():生成器{
试一试{
const appStateChannel=产生调用(createAppStateChannel);
while(true){
const nextapstate:nextapstate=yield take(appStateChannel);
如果(nextAppState===“活动”){
//执行一些操作,例如与服务器同步
}
}最后{
如果(收益率已取消()){
appStateChannel.close();
}
} 
}
我正在考虑JS上下文因任何原因被杀死的情况

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


任何人都可以告诉我这是否安全,或者使用HOC是否基本上更好?我也使用react本机导航,其中有多个react根视图(每个屏幕一个),这就是为什么HOC不适合这种情况,因为我必须用HOC包装每个父屏幕,而且如果我有3个屏幕被推到堆栈上,那么在app resume上,逻辑将执行3次。

因此,显然这取决于本机模块的实现

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

然而,如果在本机端处理新的侦听器,那么如果JS上下文被终止,则会出现问题,因为内存会泄漏

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

您可以在此处查看
AppState
的源代码作为示例:

我还没有偶然发现一个模块可以反过来做。 根据经验,只要浏览一下github源代码上的模块,就可以了解订阅是如何管理的