web-dev-qa-db-fra.com

L'application React-native est redémarrée sur chaque navigation lorsqu'elle est intégrée à l'application native

Nous essayons d'intégrer une nouvelle application React Native à une application native Android application. En suivant l'officiel RN docs nous avons réussi pour le faire fonctionner mais avec quelques problèmes concernant la navigation.

Nous avons des écrans natifs et non natifs (JS), et nous avons besoin d'un bon moyen pour naviguer entre tous les écrans, que l'écran soit natif ou non.

Nous avons essayé d'adopter native-navigation et react-native-navigation pour voir si certains résolvent notre problème mais aucun d'entre eux n'a réellement fonctionné.

Actuellement, nous avons enregistré tous nos écrans RN comme ceci:

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

    const store = configureStore();

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

Nous avons également créé un module natif que nous appelons "Navigateur" qui a une méthode de navigation appelée openComponent qui accepte le nom d'écran et ses accessoires. Voici à quoi ressemble l'implémentation de 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());
         }
     }

Ensuite, chaque fois que nous voulons naviguer du côté RN, nous appelons simplement notre navigateur personnalisé avec les accessoires d'écran cible.

Le problème avec l'approche actuelle est que la partie RN est redémarrée chaque fois que nous naviguons vers des écrans basés sur RN, ce qui entraîne le vide du magasin Redux.

Voici à quoi ressemble notre méthode "onCreate" pour notre classe 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);
    }
33
usef_ksa

En fait, pour votre cas de question, vous devriez télécharger une petite échelle de votre projet qui a ce problème sur Gitlab ou Github et mettre son lien ici, donc nous pourrions aider mieux.

En effet, je suis JavaScript, React, React Native développeur et je ne peux aider personne du côté natif, mais je pense que vous et vos collègues choisissez la mauvaise voie pour votre application.

React Native est un projet JavaScript instable qui a des codes natifs instables qui changent dans le temps, vous devez donc écrire toutes vos fonctionnalités simplement en utilisant JavaScript. Tout comme Sophie Albert a dit dans cet article , Ils veulent faire un gros changement en React Native, Donc, il vaut mieux que tous les codes soient écrits en JavaScript non natifs (Java, Objective C).

Au début, je crois que vous avez choisi react-native-navigation était faux. Pourquoi vous n'utilisez pas react-navigation ?

Parce que 99,7% des react-navigation basé sur JavaScript et en changeant les côtés natifs par les équipes Facebook, n'affecte pas votre projet et le développement et le débogage est très facile. absolument, vous pouvez utiliser toutes les bibliothèques de tendances comme Redux, à cause de votre projet basé sur JavaScript.

Mes collègues et moi développons une large échelle React Native application pour Sheypoor , à l'exception de l'écran de démarrage, toute l'application basée sur JavaScript et dans nos tests d'entrées, nous n'avons pas eu un seul crash ou erreur ou redémarrage indésirable.

Si cela vous est possible, restaurez votre navigation dans une bibliothèque de navigation complète JavaScript comme react-navigation que nous avons choisi. Si vous avez téléchargé un référentiel de reproduction, je pourrais vous aider mieux que cette situation. mais j'ai mis une partie de notre structure de code pour vous aider à revenir à react-navigation:

Le index.js de notre projet:

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

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

Le fichier racine de notre application, le App.js fichier:

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;

Le RootNavigation.js fichier, mais ce n'est pas le cas pour nos validations antérieures. Je ne mets pas la nouvelle version en raison de sa complexité:

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

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

export default RootNavigation;

Et enfin, la version antérieure de 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"
    ]
  }
}

Avec ces codes et configurations, nous n'avons donné aucune erreur.

1
AmerllicA

Dans le ReactActivity.Java on peut vérifier Bundle savedInstanceState

... afin de contrôler le moment où l'application React est instanciée:

@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);
    }
}
0
Martin Zeitler