在React Native Navigation中使用Wix注册React Native Code Push

5
我使用的是react-native-code-push插件。它提供了客户端集成CodePush服务的功能,让你可以轻松地为React Native应用添加动态更新体验。
但是,在一些原生导航的实现中(例如react-native-navigation),并没有根组件。应用程序将开始调用类似于以下函数的方法:
// index.js

import { Navigation } from 'react-native-navigation';

Navigation.startTabBasedApp({
  tabs: [
    {
      label: 'One',
      screen: 'example.FirstTabScreen', // this is a registered name for a screen
      icon: require('../img/one.png'),
      selectedIcon: require('../img/one_selected.png'), // iOS only
      title: 'Screen One'
    },
    {
      label: 'Two',
      screen: 'example.SecondTabScreen',
      icon: require('../img/two.png'),
      selectedIcon: require('../img/two_selected.png'), // iOS only
      title: 'Screen Two'
    }
  ]
});
// or a single screen app like:
Navigation.registerComponent('example.MainApplication', () => MainComponent);

Navigation.startSingleScreenApp({
  screen: {
    screen: 'example.MainApplication', 
    navigatorButtons: {}, 
    navigatorStyle: {
      navBarHidden: true
    }
  },

})

因为没有根组件,所以不清楚在哪里调用CodePush,通常我应该像高阶组件一样将整个根组件包装在CodePush中。

我曾经做的是:

// index.js
class MyRootComponent extends Component {
  render () {
    return <MainNavigator/> // a navigator using react-navigation
  }
}

let codePushOptions = {
  checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
  installMode: CodePush.InstallMode.ON_NEXT_RESUME
}


export default CodePush(codePushOptions)(MyRootComponent)

有没有正确的方法来解决这个问题!?


我知道我可以这样做:

Navigation.registerComponent('example.MainApplication', () => CodePush(codePushOptions)(RootComponent));

Navigation.startSingleScreenApp({
  screen: {
    screen: 'example.MainApplication', 
    navigatorButtons: {},
    navigatorStyle: {
      navBarHidden: true
    }
  },

})

但是我应该仅使用导航器来投影我的根组件,这似乎不是一个好主意。我认为这个问题可能有一个最佳实践,我正在寻找。


更新

我认为在react-native-navigation中注册选项卡导航器存在一些复杂性,至少我无法解决这个问题。例如,在react-native-navigation中使用react-native-code-pushtabBasedApp就是我所需要的。

3个回答

7

感谢之前提供的代码片段。我能够使用以下代码在react-native-navigation V2中在应用恢复时检查代码推送并立即更新,而无需为codePush创建包装组件。这是应用程序启动逻辑的相关部分。

    Navigation.events().registerAppLaunchedListener(() => {
      console.log('Navigation: registerAppLaunchedListener ')
      start()
    })

    function checkCodePushUpdate () {
      return  codePush.sync({
        checkFrequency: codePush.CheckFrequency.ON_APP_RESUME,
        installMode: codePush.InstallMode.IMMEDIATE,
        deploymentKey: CODEPUSH_KEY,
      })
    }

    function start () {
      checkCodePushUpdate ()
        .then(syncStatus => {
          console.log('Start: codePush.sync completed with status: ', syncStatus)
          // wait for the initial code sync to complete else we get flicker
          // in the app when it updates after it has started up and is
          // on the Home screen
          startApp()
          return null
        })
        .catch(() => {
          // this could happen if the app doesn't have connectivity
          // just go ahead and start up as normal
          startApp()
        })
    }

    function startApp() {
      AppState.addEventListener('change', onAppStateChange)
      startNavigation()
    }

    function onAppStateChange (currentAppState) {
      console.log('Start: onAppStateChange: currentAppState: ' + currentAppState)
      if (currentAppState === 'active') {
        checkCodePushUpdate()
      }
    }

    function startNavigation (registered) {
      console.log('Start: startNavigation')

      registerScreens()

      Navigation.setRoot({
        root: {
          stack: {
            children: [{
              component: {
                name: 'FirstScreen,
              },
            }],
          },
        },
      })
    }

5
我用以下方法让它工作了,尽管这是针对RNN v2的。
// index.js
import App from './App';
const app = new App();

// App.js
import CodePush from 'react-native-code-push';
import { Component } from 'react';
import { AppState } from 'react-native';
import { Navigation } from 'react-native-navigation';
import configureStore from './app/store/configureStore';
import { registerScreens } from './app/screens';

const appStore = configureStore();
registerScreens(appStore, Provider);

const codePushOptions = {
  checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
  updateDialog: true,
  installMode: CodePush.InstallMode.IMMEDIATE
};

export default class App extends Component {
    constructor(props) {
        super(props);
        // Set app state and listen for state changes
        this.appState = AppState.currentState;
        AppState.addEventListener('change', this.handleAppStateChange);

        this.codePushSync();
        Navigation.events().registerAppLaunchedListener(() => {
            this.startApp();
        });
    }

    handleAppStateChange = nextAppState => {
        if (this.appState.match(/inactive|background/) && nextAppState === 'active') {
            this.handleOnResume();
        }
        this.appState = AppState.currentState;
    };

    codePushSync() {
        CodePush.sync(codePushOptions);
    }


    handleOnResume() {
        this.codePushSync();
        ...
    }

    startApp() {
        Navigation.setRoot({
            root: {
                stack: {
                    children: [
                        {
                            component: {
                                name: 'MyApp.Login'
                            }
                        }
                    ]
                }
            }
        });
    }
}

// app/screens/index.js
import CodePush from 'react-native-code-push';
import { Navigation } from 'react-native-navigation';
import Login from './Login';

function Wrap(WrappedComponent) {
    return CodePush(WrappedComponent);
}

export function registerScreens(store, Provider) {
    Navigation.registerComponentWithRedux(
        'MyApp.Login',
        () => Wrap(Login, store),
        Provider,
        store.store
    );
    ...
}

1
非常感谢。在App.js的这个位置添加registerScreens();保存了我的项目。 - Luat Vu Dinh

2
我已经找到了答案。 看一下这个示例项目结构:
.
├── index.js
├── src
|   └── app.js
└── screens
    ├── tab1.html
    └── tab2.html

你可以在 index.js 文件中注册你的 code-push

//index.js
import { AppRegistry } from 'react-native';
import App from './src/app';
import CodePush from 'react-native-code-push'

let codePushOptions = {
  checkFrequency: CodePush.CheckFrequency.ON_APP_RESUME,
  installMode: CodePush.InstallMode.ON_NEXT_RESUME
}

AppRegistry.registerComponent('YourAppName', () => CodePush(codePushOptions)(App));

现在,您可以像这样在app.js中启动react-native-navigation

import {Navigation} from 'react-native-navigation';
import {registerScreens, registerScreenVisibilityListener} from './screens';

registerScreens();
registerScreenVisibilityListener();

const tabs = [{
  label: 'Navigation',
  screen: 'example.Types',
  icon: require('../img/list.png'),
  title: 'Navigation Types',
}, {
  label: 'Actions',
  screen: 'example.Actions',
  icon: require('../img/swap.png'),
  title: 'Navigation Actions',
}];

Navigation.startTabBasedApp({
  tabs,
  tabsStyle: {
    tabBarBackgroundColor: '#003a66',
    tabBarButtonColor: '#ffffff',
    tabBarSelectedButtonColor: '#ff505c',
    tabFontFamily: 'BioRhyme-Bold',
  },
  appStyle: {
    tabBarBackgroundColor: '#003a66',
    navBarButtonColor: '#ffffff',
    tabBarButtonColor: '#ffffff',
    navBarTextColor: '#ffffff',
    tabBarSelectedButtonColor: '#ff505c',
    navigationBarColor: '#003a66',
    navBarBackgroundColor: '#003a66',
    statusBarColor: '#002b4c',
    tabFontFamily: 'BioRhyme-Bold',
  }
});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接