循环依赖在 React Native 中返回空对象 [英] Cyclic dependency returns empty object in React Native

查看:50
本文介绍了循环依赖在 React Native 中返回空对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个相互导航的 React Native 组件(Alpha 和 Beta);然而,这会产生循环依赖,而 React Native 似乎无法处理这些.

I have two React Native Components (Alpha and Beta) that navigate to one another; however, this produces a cyclic dependency and React Native doesn’t seem to handle those.

在 Alpha 中要求 Beta 工作正常,但在 Beta 中要求 Alpha 返回一个空对象.尝试推送包含无效组件的路由时会引发错误.

Requiring Beta in Alpha works fine, but requiring Alpha in Beta returns an empty object. An error is thrown when trying to push a route with an invalid component.

循环依赖可以在 React Native 中工作吗?如果没有,我该如何解决这个问题?

Can cyclic dependencies work in React Native? If not, how do I get around this?

index.ios.js

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;

推荐答案

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

This is a common problem with routing components. There are a couple of ways to approach this. In general, you want Alpha to avoid requiring Beta before Alpha has defined its exports and vice versa.

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

Fortunately, JavaScript's import and export keywords address this issue by lazily importing values using an intermediate object that acts as a level of indirection. A specific example is a lot easier to understand.

使用export关键字从各自的文件中导出Alpha和Beta,使用import关键字导入:

Use the export keyword to export Alpha and Beta from their respective files, and use the import keyword to import them:

// Alpha.js
import Beta from './Beta';

var Alpha = React.createClass({
    /* ... */
});
export default Alpha;

这是可行的,因为在运行时,export 关键字创建了一个中间对象(相当于 CommonJS 中的 module.exports)并分配了一个名为 default 的属性code> 与 Alpha 的值.所以,上面的 export 语句在概念上类似于:

This works because at runtime, the export keyword creates an intermediate object (equivalent to module.exports in CommonJS) and assigns a property named default to it with the value of Alpha. So, the above export statement is conceptually similar to this:

module.exports.default = Alpha;

导入 Alpha 的文件然后获得对中间对象的引用,而不是 Alpha 本身,直到直接使用 Alpha.所以这里的这段代码实际上是懒惰地访问Alpha:

The files that import Alpha then get a reference to the intermediate object, not Alpha itself until Alpha is directly used. So this code here actually lazily accesses Alpha:

import Alpha from './Alpha';

var ExampleProject = React.createClass({
    render() {
        return (
            <NavigatorIOS
                style={styles.container}
                initialRoute={{
                    component: Alpha,
                    title: Alpha.title,
                    wrapperStyle: styles.wrapper
                }}
            />
        );
    },
});

惰性访问是通过运行概念上类似于此的代码来实现的:

The lazy access is implemented by running code conceptually similar to this:

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
                }}
            />
        );
    },
});

<小时>

使用 require()

使用 CommonJS 的 require,您还有其他一些选择:


With require()

Using CommonJS's require, you have some other options:

Alpha 和 Beta 不需要彼此,直到用户从一个场景导航到另一个场景.要使应用程序达到此状态,Alpha 必须已定义其导出(即 module.exports = Alpha 必须已运行,您的应用程序才能呈现 Alpha 组件).因此,当用户导航到显示 Beta 的场景时,Beta 需要 Alpha 是安全的,因此此时需要 Beta 是安全的.

Alpha and Beta don't need each other until the user navigates from one scene to the next. For the app to reach this state, Alpha must have defined its exports (that is, module.exports = Alpha must have run for your app to have rendered an Alpha component). So, when the user is navigating to the scene displaying Beta, it is safe for Beta to require Alpha and therefore it is safe to require Beta at this point in time.

// 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
        });
    }
});

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

Although it isn't necessary to do the same for Beta.js in this specific scenario because Alpha is the first component loaded, it's probably a good idea so that your components all handle dependency cycles the same way.

另一种解决方案是将Alpha和Beta放在同一个JS文件中,去掉模块之间的循环.然后,您将从新的大型模块中导出这两个组件.

Another solution is to put Alpha and Beta in the same JS file to remove a cycle between modules. You would then export both components from the new mega-module.

// AlphaBeta.js
var Alpha = React.createClass({...});
var Beta = React.createClass({...});
exports.Alpha = Alpha;
exports.Beta = Beta;

要求:

// index.js
var {Alpha, Beta} = require('./AlphaBeta');

这篇关于循环依赖在 React Native 中返回空对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆