我有两个相互导航的React Native组件(Alpha和Beta);但是,这会产生循环依赖,而React Native似乎无法处理这些依赖。
在Alpha中要求Beta工作正常,但在Beta中要求Alpha返回一个空对象。尝试使用无效组件推送路由时会引发错误。
循环依赖可以在React Native中使用吗?如果没有,我该如何解决这个问题?
index.ios.js
'use strict';
var React = require('react-native');
var Alpha = require('./Alpha');
var {
AppRegistry,
NavigatorIOS,
StyleSheet,
Text,
View,
} = React;
var ExampleProject = React.createClass({
render() {
return (
<NavigatorIOS
style={styles.container}
initialRoute={{
component: Alpha,
title: Alpha.title,
wrapperStyle: styles.wrapper
}} />
);
},
});
var styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white'
},
wrapper: {
paddingTop: 64
}
});
AppRegistry.registerComponent('ExampleProject', () => ExampleProject);
Alpha.js
'use strict';
var React = require('react-native');
var Beta = require('./Beta');
var {
StyleSheet,
TouchableHighlight,
View,
Text
} = React;
var Alpha = React.createClass({
statics: {
title: 'Alpha'
},
goToBeta() {
this.props.navigator.push({
component: Beta,
title: Beta.title,
wrapperStyle: styles.wrapper
});
},
render() {
return (
<View>
<TouchableHighlight style={styles.linkWrap}
onPress={this.goToBeta}>
<Text>Go to Beta</Text>
</TouchableHighlight>
</View>
);
}
});
var styles = StyleSheet.create({
linkWrap: {
flex: 1,
alignItems: 'center',
padding: 30
},
wrapper: {
paddingTop: 64
}
});
module.exports = Alpha;
Beta.js
'use strict';
var React = require('react-native');
var Alpha = require('./Alpha');
var {
StyleSheet,
TouchableHighlight,
View,
Text
} = React;
var Beta = React.createClass({
statics: {
title: 'Beta'
},
goToAlpha() {
this.props.navigator.push({
component: Alpha,
title: Alpha.title,
wrapperStyle: styles.wrapper
});
},
render() {
return (
<View>
<TouchableHighlight style={styles.linkWrap}
onPress={this.goToAlpha}>
<Text>Go to Alpha</Text>
</TouchableHighlight>
</View>
);
}
});
var styles = StyleSheet.create({
linkWrap: {
flex: 1,
alignItems: 'center',
padding: 30
},
wrapper: {
paddingTop: 64
}
});
module.exports = Beta;
答案 0 :(得分:26)
这是路由组件的常见问题。有几种方法可以解决这个问题。通常,您希望Alpha在Alpha定义其导出之前避免要求Beta,反之亦然。
幸运的是,JavaScript的import
和export
关键字通过使用充当间接级别的中间对象延迟导入值来解决此问题。一个具体的例子更容易理解。
import
和export
使用export
关键字从各自的文件中导出Alpha和Beta,然后使用import
关键字导入它们:
// Alpha.js
import Beta from './Beta';
var Alpha = React.createClass({
/* ... */
});
export default Alpha;
这是有效的,因为在运行时,export
关键字创建一个中间对象(相当于CommonJS中的module.exports
),并为其分配一个名为default
的属性,其值为{{1 }}。因此,上述Alpha
语句在概念上与此类似:
export
导入Alpha的文件然后在直接使用module.exports.default = Alpha;
之前获取对中间对象的引用,而不是Alpha本身。所以这段代码实际上懒得访问Alpha:
Alpha
延迟访问是通过运行代码来实现的,类似于:
import Alpha from './Alpha';
var ExampleProject = React.createClass({
render() {
return (
<NavigatorIOS
style={styles.container}
initialRoute={{
component: Alpha,
title: Alpha.title,
wrapperStyle: styles.wrapper
}}
/>
);
},
});
var AlphaExports = require('./Alpha');
var ExampleProject = React.createClass({
render() {
return (
<NavigatorIOS
style={styles.container}
initialRoute={{
component: AlphaExports.default,
title: AlphaExports.default.title,
wrapperStyle: styles.wrapper
}}
/>
);
},
});
使用CommonJS的require()
,您还有其他选择:
在用户从一个场景导航到下一个场景之前,Alpha和Beta不需要彼此。为了使应用程序达到此状态,Alpha必须已定义其导出(即,require
必须已运行,以便您的应用呈现Alpha组件)。因此,当用户导航到显示Beta的场景时,Beta可以安全地要求Alpha,因此此时需要Beta是安全的。
module.exports = Alpha
虽然在这个特定的场景中没有必要对Beta.js做同样的事情,因为Alpha是第一个加载的组件,但这可能是一个好主意,所以你的组件都以相同的方式处理依赖循环。
另一个解决方案是将Alpha和Beta放在同一个JS文件中,以删除模块之间的循环。然后,您将从新的mega模块中导出两个组件。
// Alpha.js
var Alpha = React.createClass({
goToBeta() {
// Lazily require Beta, waiting until Alpha has been initialized
var Beta = require('./Beta');
this.props.navigator.push({
component: Beta,
title: Beta.title,
wrapperStyle: styles.wrapper
});
}
});
要求它:
// AlphaBeta.js
var Alpha = React.createClass({...});
var Beta = React.createClass({...});
exports.Alpha = Alpha;
exports.Beta = Beta;