新しいReactネイティブアプリを既存のネイティブAndroidアプリに統合します。RN公式に従います docs それを機能させるには、ナビゲーションに関するいくつかの問題があります。
ネイティブ画面と非ネイティブ(JS)画面があります。画面がネイティブかどうかに関係なく、すべての画面間を移動するための優れた方法が必要です。
native-navigation と react-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);
}
実際、質問の場合は、GitlabまたはGithubにこの問題が発生しているプロジェクトの小さな小さなスケールをアップロードし、そのリンクをここに配置する必要があります。
確かに、私はJavaScript
、React
、React 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つも発生しませんでした。
の中に 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);
}
}