web-dev-qa-db-ja.com

ネイティブアプリと統合すると、すべてのナビゲーションでReactネイティブアプリが再起動されます

新しいReactネイティブアプリを既存のネイティブAndroidアプリに統合します。RN公式に従います docs それを機能させるには、ナビゲーションに関するいくつかの問題があります。

ネイティブ画面と非ネイティブ(JS)画面があります。画面がネイティブかどうかに関係なく、すべての画面間を移動するための優れた方法が必要です。

native-navigationreact-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と呼ばれるナビゲーションメソッドを持つ「Navigator」と呼ばれるネイティブモジュールも作成しました。 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ストアが空になることです。

ここでは、ReactActivity.Javaクラスの「onCreate」メソッドがどのように見えるかを示します。

@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

実際、質問の場合は、GitlabまたはGithubにこの問題が発生しているプロジェクトの小さな小さなスケールをアップロードし、そのリンクをここに配置する必要があります。

確かに、私はJavaScriptReactReact Native開発者であり、ネイティブ側の誰も助けることはできませんが、間違いなく、あなたとあなたの同僚は間違った方法を選択していると思いますあなたの申請。

React Nativeは不安定なJavaScriptプロジェクトであり、時間とともに変化する不安定なネイティブコードがあるため、JavaScriptを使用してすべての機能を記述する必要があります。 Sophie Albertこの記事 で言ったように、彼らはReact Nativeに大きな改行を加えたいので、すべてのコードを記述する方が良いJavaScriptはネイティブではありません(Java、Objective C)。

最初は、 react-native-navigation の選択が間違っていたと思います。なぜ react-navigation を使用しないのですか?

JavaScriptに基づくreact-navigationの99.7%とFacebookチームによるネイティブ側の変更のため、プロジェクトに影響を与えず、開発とデバッグは非常に簡単です。プロジェクトはReduxに基づいているため、JavaScriptのようなすべてのトレンドライブラリを使用できます。

私の同僚と私は Sheypoor 用の大規模なReact Nativeアプリケーションを開発していますが、スプラッシュスクリーンはJavaScriptに基づくすべてのアプリを除き、入力テストでは使用していませんクラッシュ、エラー、または不要な再起動が1回でも発生します。

可能であれば、ナビゲーションをreact-navigationのような完全なJavaScriptナビゲーションライブラリにロールバックしてください。複製リポジトリをアップロードした場合、私はこの状況よりもあなたを助けることができます。ただし、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ファイル:

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"
    ]
  }
}

これらのコードと構成により、エラーは1つも発生しませんでした。

1
AmerllicA

の中に 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);
    }
}
0
Martin Zeitler