React-native-приложение перезапускается при каждой навигации при интеграции с нативным приложением. - PullRequest
0 голосов
/ 25 сентября 2018

Мы пытаемся интегрировать новое приложение React Native в существующее нативное приложение Android.Вслед за официальным документом RN docs нам удалось заставить его работать, но с некоторыми проблемами, связанными с навигацией.

У нас есть родные и не родные (JS) экраны, и нам нужен хороший способперемещаться между всеми экранами независимо от того, является ли экран родным или нет.

Мы попытались использовать native-navigation и response-native-navigation , чтобы выяснить, решен ли какой-либо из этих вопросов, но ни один из них на самом деле не работает.

В настоящее время мы зарегистрировали все наши экраны RN следующим образом:

const provide = (store, Screen) => {
      return props => (
        <Provider store={store}>
          <Screen {...props} />
        </Provider>
      );
    };

    const store = configureStore();

    AppRegistry.registerComponent('Home', () => provide(store, HomeComponent));

Мы также создали собственный модуль, который мы называем «Навигатор», у которого есть метод навигации с именем openComponent, который принимает имя экрана и его параметры.Вот как выглядит реализация openComponent:

// our native module code ...
     @ReactMethod
     public void openComponent(String name, String extra) {

         try {
             Intent intent = new Intent(this.getReactApplicationContext(), MyReactActivity.class);
             intent.putExtra("moduleName", name);
             intent.putExtra("extra", extra);

             getCurrentActivity().startActivityForResult(intent, 0);
         }
         catch (Exception e) {
             e.printStackTrace();
             Crashlytics.logException(e.getCause());
         }
     }

Затем, когда мы хотим ориентироваться на стороне RN, мы просто вызываем наш пользовательский навигатор с опорами целевого экрана.

Проблема с текущим подходом состоит в том, что часть RN перезапускается всякий раз, когда мы переходим к экранам на основе RN, что приводит к пустому хранилищу Redux.

Здеськак наш метод onCreate выглядит для нашего класса ReactActivity.java:

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        Bundle initialProperties = new Bundle();
        initialProperties.putString("loginToken", HJSession.getSession().getSessionId());
        initialProperties.putString("username", HJSession.getSession().getUserName());
        initialProperties.putString("userId", HJSession.getSession().getUserId().toString());

        String moduleName = "topics";
        Bundle bundle = getIntent().getExtras();

        if (bundle != null) {
            moduleName = bundle.getString("moduleName");
            try {
                String extra = bundle.getString("extra");
                initialProperties.putString("extra", extra);
            }
            catch (Exception e) {
                e.printStackTrace();
                Crashlytics.logException(e.getCause());
            }
        }

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setJSMainModulePath("index")
                .addPackages(Arrays.<ReactPackage>asList(
                        new MainReactPackage(),
                        new RNFirebasePackage(),
                        new RNFirebaseMessagingPackage(),
                        new RNFirebaseNotificationsPackage(),
                        new RNI18nPackage(),
                        new VectorIconsPackage(),
                        new HJRNPackages(),
                        new NativeNavigationPackage()
                ))
                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

        mReactRootView.startReactApplication(mReactInstanceManager, moduleName, initialProperties);

        setContentView(mReactRootView);
    }

Ответы [ 2 ]

0 голосов
/ 04 октября 2018

На самом деле, для вашего вопроса вы должны загрузить небольшой крошечный масштаб вашего проекта, который имеет эту проблему, на Gitlab или Github и поставить ссылку здесь, следовательно, мы могли бы помочь лучше.

Действительно, я 'Я JavaScript, React, React Native разработчик, и я не могу помочь никому на родной стороне, но, безусловно, я верю, что вы и ваши коллеги выбрали неправильный путь для вашего приложения.

React Nativeэто нестабильный JavaScript проект, который имеет нестабильные собственные коды, которые меняются во времени, поэтому вы должны написать все свои функции, просто используя JavaScript.Точно так же, как Софи Альберт сказал в этой статье , они хотят сделать большой перерыв на React Native, поэтому лучше, чтобы все коды были написаны в JavaScript, а неnative (Java, Objective C).

Сначала я считаю, что вы выбрали react-native-navigation неправильно.Почему вы не используете react-navigation?

Поскольку 99,7% react-navigation на основе JavaScript и смена сторон в группах Facebook не влияют на ваш проект, разработку и отладкуочень легко.безусловно, вы можете использовать любую библиотеку трендов, например, Redux, поскольку ваш проект основан на JavaScript.

. Мы с коллегами разрабатываем крупномасштабное приложение React Native для Sheypoor За исключением заставки для всех приложений, основанных на JavaScript, и в наших тестах ввода мы не получили ни одного сбоя, ошибки или нежелательного перезапуска.

Если это возможно, откатите навигациюв полную JavaScript библиотеку навигации, такую ​​как react-navigation, которую мы выбрали.Если вы загрузили репозиторий репродукций, я мог бы помочь вам лучше, чем эта ситуация.но я поместил часть нашей структуры кода, чтобы помочь вам вернуться к react-navigation:

index.js нашего проекта:

import { AppRegistry } from 'react-native';
import App from './app/App';
import { name as appName } from './app.json';

AppRegistry.registerComponent(appName, () => App);

Корневой файл нашего приложения,App.js file:

import React from 'react';
import { Provider } from 'react-redux';
import RootNavigation from './RootNavigation';
import { onNavigationStateChange } from './utils/routes';
import configureStore from './redux/configureStore';

const store = configureStore();

const App = () => (
  <Provider store={store}>
    <RootNavigation onNavigationStateChange={onNavigationStateChange} />
  </Provider>
);

export default App;

Файл RootNavigation.js, но он для наших предыдущих коммитов не сейчас.Я не ставлю более новую версию из-за ее сложности:

import { createSwitchNavigator } from 'react-navigation';
import { Loading, Dashboard, SignInStack, ListingManagement } from './screens';

const RootNavigation = createSwitchNavigator(
  {
    Loading,
    SignInStack,
    Dashboard,
    ListingManagement
  },
  {
    initialRouteName: 'SignInStack'
  }
);

export default RootNavigation;

И наконец, более ранняя версия package.json:

{
  "name": "sheypoor",
  "version": "0.0.1",
  "private": true,
  "scripts": {
    "start": "node node_modules/react-native/local-cli/cli.js start",
    "android": "npx react-native run-android",
    "ios": "npx react-native run-ios",
    "physical-android": "react-native bundle --platform android --dev false --entry-file index.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res",
    "test": "jest",
    "eslint": "eslint .",
    "clean": "react-native-clean-project",
    "pre-commit": "lint-staged"
  },
  "lint-staged": {
    "*.js": [
      "eslint --fix ."
    ]
  },
  "dependencies": {
    "formik": "^1.3.0",
    "lint-staged": "^7.3.0",
    "prop-types": "^15.6.2",
    "react": "16.5.0",
    "react-native": "0.57.1",
    "react-native-confirmation-code-field": "^1.2.2",
    "react-native-vector-icons": "^5.0.0",
    "react-navigation": "^2.16.0",
    "react-redux": "^5.0.7",
    "redux": "^4.0.0",
    "yup": "^0.26.6"
  },
  "devDependencies": {
    "babel-eslint": "^9.0.0",
    "babel-jest": "23.6.0",
    "babel-plugin-module-resolver": "^3.1.1",
    "babel-plugin-root-import": "^6.1.0",
    "eslint": "^5.5.0",
    "eslint-config-airbnb": "^17.1.0",
    "eslint-config-prettier": "^3.0.1",
    "eslint-import-resolver-babel-plugin-root-import": "^1.1.1",
    "eslint-plugin-flowtype": "^2.50.0",
    "eslint-plugin-import": "^2.14.0",
    "eslint-plugin-jsx-a11y": "^6.1.1",
    "eslint-plugin-prettier": "^2.6.2",
    "eslint-plugin-react": "^7.11.1",
    "eslint-plugin-react-native": "^3.3.0",
    "eslint-plugin-sort-imports-es6-autofix": "^0.3.0",
    "flow-bin": "^0.78.0",
    "jest": "23.6.0",
    "metro-react-native-babel-preset": "0.45.6",
    "prettier": "^1.14.3",
    "react-native-clean-project": "^3.0.0",
    "react-native-config": "^0.11.5",
    "react-test-renderer": "16.5.0",
    "redux-devtools-extension": "^2.13.5"
  },
  "jest": {
    "preset": "react-native"
  },
  "rnpm": {
    "assets": [
      "./app/assets/fonts"
    ]
  }
}

С этими кодами и конфигурациями мыне дал ни одной ошибки.

0 голосов
/ 04 октября 2018

В ReactActivity.java можно проверить Bundle savedInstanceState

..., чтобы контролировать, когда создается приложение React:

@Override
protected void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);

    /* it's always NULL on first run */
    if (savedInstanceState == null) {

        Bundle initialProperties = new Bundle();
        initialProperties.putString("loginToken", HJSession.getSession().getSessionId());
        initialProperties.putString("username", HJSession.getSession().getUserName());
        initialProperties.putString("userId", HJSession.getSession().getUserId().toString());

        String moduleName = "topics";
        Bundle bundle = getIntent().getExtras();

        if (bundle != null) {
            moduleName = bundle.getString("moduleName");
            try {
                String extra = bundle.getString("extra");
                initialProperties.putString("extra", extra);
            } catch (Exception e) {
                Crashlytics.logException(e.getMessage());
                Log.e("ReactActivity", e.getMessage());
            }
        }

        mReactRootView = new ReactRootView(this);
        mReactInstanceManager = ReactInstanceManager.builder()
            .setApplication(getApplication())
            .setJSMainModulePath("index")
            .addPackages(Arrays.<ReactPackage>asList(
                new MainReactPackage(),
                new RNFirebasePackage(),
                new RNFirebaseMessagingPackage(),
                new RNFirebaseNotificationsPackage(),
                new RNI18nPackage(),
                new VectorIconsPackage(),
                new HJRNPackages(),
                new NativeNavigationPackage()
            ))
            .setUseDeveloperSupport(BuildConfig.DEBUG)
            .setInitialLifecycleState(LifecycleState.RESUMED)
            .build();

        mReactRootView.startReactApplication(mReactInstanceManager, moduleName, initialProperties);
        setContentView(mReactRootView);
    }
}
...