We're trying to integrate a new React Native app to an existing native Android app. Following the RN official docs we managed to get it working but with some issues regarding the navigation.
We've native and non-native (JS) screens, and we need a good way to navigate between all screens regardless if a screen is native or not.
We tried to adopt native-navigation and react-native-navigation to see if any address our issue but none of them actually worked.
Currently, we have registered all our RN screens like this:
const provide = (store, Screen) => {
return props => (
<Provider store={store}>
<Screen {...props} />
</Provider>
);
};
const store = configureStore();
AppRegistry.registerComponent('Home', () => provide(store, HomeComponent));
We also created a Native Module we call "Navigator" that has navigation method called openComponent
that accepts screen name and its props. Here is how the implementation of openComponent
looks:
// 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());
}
}
Then whenever we want to navigate on the RN side we simply call our custom navigator with the target screen props.
The problem with the current approach is that the RN part is being restarted whenever we navigate to RN-based screens which causes the Redux store to be empty.
Here how our "onCreate" method looks like for our ReactActivity.java class:
@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);
}
Actually, for your question case, you should upload a little tiny scale of your project that has this issue on Gitlab or Github and put its link here, Hence we could help better.
Indeed, I'm a JavaScript
, React
, React Native
developer and I cannot help anybody in the native side, But definitely, I believe you and your colleagues choose the wrong way for your application.
React Native
is an unstable JavaScript
project that has unstable native codes that are changing in time, so you should write all of your features just by using JavaScript
. Just like Sophie Albert said in this article, They wanna make a big break change to React Native
, So, It is better all of the codes to be written in JavaScript
not native (Java, Objective C).
At first, I believe your choosing on react-native-navigation
was wrong. Why you do not use react-navigation
?
Because 99.7% of react-navigation
based on JavaScript
and changing native sides by Facebook teams, do not affect your project and development and debugging is very easy. absolutely, you can use every trend library like Redux
, because of your project based on JavaScript
.
My colleagues and I are developing a large scale React Native
application for Sheypoor, except the splash screen all of the app based on JavaScript
and in our inputs tests we didn't get even one crash or error or unwanted restart.
If it is possible for you, roll back your navigation to a full JavaScript
navigation library like react-navigation
which we chose. If you uploaded a reproduction repository I could help you better than this situation. but I put some of our code structure to help you for roll back to react-navigation
:
The index.js
of our project:
import { AppRegistry } from 'react-native';
import App from './app/App';
import { name as appName } from './app.json';
AppRegistry.registerComponent(appName, () => App);
The root file of our app, the 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;
The RootNavigation.js
file, but it is for our earlier commits not now. I don't put the newer version because of its complexities:
import { createSwitchNavigator } from 'react-navigation';
import { Loading, Dashboard, SignInStack, ListingManagement } from './screens';
const RootNavigation = createSwitchNavigator(
{
Loading,
SignInStack,
Dashboard,
ListingManagement
},
{
initialRouteName: 'SignInStack'
}
);
export default RootNavigation;
And at last, the earlier version of 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"
]
}
}
With these codes and configurations, we didn't give even one error.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With