循环依赖在React Native中返回空对象

时间:2015-04-22 20:01:43

标签: react-native

我有两个相互导航的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;

1 个答案:

答案 0 :(得分:26)

这是路由组件的常见问题。有几种方法可以解决这个问题。通常,您希望Alpha在Alpha定义其导出之前避免要求Beta,反之亦然。

幸运的是,JavaScript的importexport关键字通过使用充当间接级别的中间对象延迟导入值来解决此问题。一个具体的例子更容易理解。

使用importexport

使用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(),您还有其他选择:

方法1:延迟加载

在用户从一个场景导航到下一个场景之前,Alpha和Beta不需要彼此。为了使应用程序达到此状态,Alpha必须已定义其导出(即,require必须已运行,以便您的应用呈现Alpha组件)。因此,当用户导航到显示Beta的场景时,Beta可以安全地要求Alpha,因此此时需要Beta是安全的。

module.exports = Alpha

虽然在这个特定的场景中没有必要对Beta.js做同样的事情,因为Alpha是第一个加载的组件,但这可能是一个好主意,所以你的组件都以相同的方式处理依赖循环。

方法2:单一模块

另一个解决方案是将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;