getMeteorData与组件生命周期的竞争条件?

时间:2015-07-19 20:12:11

标签: meteor reactjs

我在我的应用中遇到了一些非常不受欢迎的行为,而且我很难复制问题和/或弄清楚我做错了什么或不了解React&# 39; s导致我的组件以这种方式行动。

我想要做的是在App组件上从Mongo获取一些数据,然后让所有这些数据随时可用于我想要的任何孩子。

<App> //get data here, pass to children through props
    <ChildElement1 data={this.data.appData}/>
    <ChildElement2 data={this.data.appData}/>
    <ChildElement3 data={this.data.appData}/>
</App>

到目前为止,我是如何尝试使用React解决这个问题的:

App = React.createClass({
    mixins: [ReactMeteorData],

    getMeteorData() {
        let _id = 'exampleId';
        return {
            appData: Collection.findOne({_id})
        };
    },

    render() {
        return (<ChildElement1 data={this.data.appData} />);
    }
});

ChildElement1 = React.createClass({
    getInitialState() {
        return {
            values: ['val1', 'val2', 'val3', 'val4'] //default values
        };
    },

    componentWillMount() {
        if(this.props.data.specificValues) {
            this.setState({values: this.props.data.specificValues});
        }
    },

    render() {
        let values = this.state.values;
        return (<span>{values[0]} {values[1]} {values[2]} {values[3]}</span>);
    }
});

所以在这里它变得奇怪。当我拨打componentWillMount()时,有时会定义this.props.data,有时会定义componentWillReceiveProps(nextProps),这会让我相信某些竞争条件正在进行,有时数据会被加载正确地作为道具而其他时候它没有。

然后我认为,好吧,在组件最初安装之前,我不能依赖于数据道具,所以我可以改用componentWillReceiveProps并检查更新的道具(和如有必要,更新状态)。然而!使用this.props.data后,现在ChildElement1似乎始终正确附加到componentWillReceiveProps的道具上(这意味着componentWillMount无法运行!)。

我的最终解决方案是同时使用componentWillReceivePropscomponentWillMount来解释这两种情况并在两个位置进行完全相同的检查。这个修复工作正常,但是男孩看起来很麻烦,可能表示对组件生命周期缺乏了解,流星/反应应该如何正确地进行交互,两者都完全相互作用。

我在这里肯定会有点帮助。

编辑:我提出了一个小改进 - 而不是使用componentWillReceivePropsrender来检查是否在Mongo集合中定义了特定值,我把render() { let data = this.props.data, values = (data) ? data.specificValues : this.state.values; return (<span>{values[0]} {values[1]} {values[2]} {values[3]}</span>); } 中的逻辑如此:

this.props
但是,由于我仍然不明白为什么getMeteorData在从async's map检索到数据时如此不一致,所以仍然存在某种潜在的问题。然而,这个版本有点简洁。

1 个答案:

答案 0 :(得分:0)

我找到了一个更好的方法,而不是将getMeteorData返回的数据作为道具传递给每个孩子。使用此处描述的方法:https://www.tildedave.com/2014/11/15/introduction-to-contexts-in-react-js.html,我在childContextTypes中明确列出了getChildContext<App />,然后在contextTypes中明确列出<ChildElement1 />,这允许{ {1}} this.data.appData this.context <ChildElement1 />可能<App />可能angular .module('app') .factory('stats', function($http){ return { getStats: function(path) { return $http .get(path) .then(function(result) { //resolve the promise as the data return result.data; }); } }; }); 。虽然我必须承认,声明该集合的每个单一类型都是一个主要的PITA,似乎有必要编写一个mixin(或者更确切地说,一堆mixins)来处理这些东西。