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
    }
  },

})

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


更新

我认为在 stacknavigator 中注册选项卡导航器有一些复杂性react-native-navigation,至少我无法克服这个问题。tabBasedAppreact-native-navigation的示例react-native-code-push,将是我所需要的。

4

3 回答 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,
              },
            }],
          },
        },
      })
    }
于 2018-11-11T21:06:38.867 回答
4

我是这样工作的,虽然这是针对 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
    );
    ...
}
于 2018-09-16T13:41:30.440 回答
2

我自己找到了答案。看这个示例项目结构:

.
├── index.js
├── src
|   └── app.js
└── screens
    ├── tab1.html
    └── tab2.html

你可以注册你code-pushindex.js

//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));

现在你可以react-native-navigationapp.js这样开始:

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',
  }
});
于 2018-05-20T11:48:54.650 回答