我们正在尝试将新的React Native应用程序集成到现有的本机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
的导航方法,该方法接受屏幕名称及其道具。 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);
}
答案 0 :(得分:0)
在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);
}
}
答案 1 :(得分:0)
实际上,对于您遇到的问题,您应该在Gitlab或Github上上传有此问题的项目的很小一部分,并将其链接放在此处,因此我们可以提供更好的帮助。
实际上,我是JavaScript
,React
,React Native
的开发人员,我无法帮助任何本地用户,但是绝对可以,我相信您和您的同事选择了错误的方式为您的应用程序。
React Native
是一个不稳定的JavaScript
项目,具有不稳定的本地代码,这些代码会随时间而变化,因此您应该仅使用JavaScript
来编写所有功能。就像Sophie Albert在this article中所说的那样,他们想对React Native
进行较大的更改,因此,最好使用JavaScript
而不是本机( Java,目标C)。
起初,我认为您在react-native-navigation
上的选择是错误的。为什么不使用react-navigation
?
由于基于react-navigation
的{{1}}的99.7%以及Facebook团队更改的原生方面,因此不会影响您的项目,因此开发和调试非常容易。绝对可以,因为您的项目基于JavaScript
,因此可以使用Redux
之类的所有趋势库。
我和我的同事正在为Sheypoor开发一个大型JavaScript
应用程序,除了初始屏幕上所有基于React Native
的应用程序,在输入测试中我们都没有得到甚至是一次崩溃,错误或意外重启。
如果可能的话,将导航回滚到我们选择的完整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
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
使用这些代码和配置,我们什至没有给出一个错误。