Meteor React рендерится дважды после того, как подписка готова

Я использую Meteor с реакцией и FlowRouter для обработки подписок. Я обнаружил, что когда мой компонент рендерится, он будет рендериться дважды через несколько секунд, но только если у меня есть метеорный миксин, подписанный на подписку.

Например:

зарегистрировано это.данные

PeoplePage = React.createClass({
    displayName:"People",
    mixins: [ReactMeteorData],
    getMeteorData() {
        const subHandles = [
            Meteor.subscribe("allPeople"),
        ];

        const subsReady = _.all(subHandles, function (handle) {
            return handle.ready();
        });

        return {
            subsReady: subsReady,
            people: People.find({}).fetch(),
        };
    },
    render(){
        if(this.data.subsReady == false){
            return (<Loading/>);
        } else {
            console.log(this.data);

            ........

        }

Одна и та же информация отображается дважды. Это связано с быстрым рендерингом, который использует FlowRouter, или это что-то, что я делаю неправильно?


person Dan    schedule 25.08.2015    source источник
comment
Как это выглядит, если вы переместите console.log наверх, чтобы он перехватывал оба состояния subsReady? Если подписка в getMeteorData верна, она не добавит вторую подписку, если она у вас уже есть, и позаботится о том, чтобы подписка была отменена, когда вы покинете страницу, без необходимости что-либо делать. Тем не менее, я предполагаю, что вы уже сказали Flowrouter подписаться на него, чтобы использовать быстрый рендеринг, поэтому вы, вероятно, могли бы пропустить все это вместе.   -  person Jimmy Stenke    schedule 25.09.2015


Ответы (2)


Хм, я думаю, проблема в том, что вы запускаете подписку каждый раз, когда компонент перерисовывается. Я не пробовал, но вы можете проверить, решит ли это проблему.

getMeteorData() {
    const subsReady = _.all(this.subs || [{}], function (handle) {
        if (typeof handle.ready == 'function') 
            return handle.ready();

        return false;
    });

    if (!subsReady) // you can extend it, to provide params to subscriptions
        this.subs = [
           Meteor.subscribe("allPeople")
        ];

    return {
        subsReady: subsReady,
        people: People.find({}).fetch(),
    }
}

Он не должен запускать сабвуферы, если они уже готовы.

Имейте в виду, что нельзя передавать пустой массив в _.all из-за этого:

_.all([], function(a) {return a.b()}) // true

вот почему я добавил пустой объект в массив, чтобы вы могли проверить наличие готового члена.

person webdeb    schedule 20.09.2015
comment
Пробовал это, @webdeb Это фактически создает бесконечный цикл. - person Dan; 27.09.2015

Я бы предложил сделать подписку внутри функции componentWillMount(). Таким образом, вы убедитесь, что подписываетесь только один раз перед начальным рендерингом().

getMeteorData() {
    var ready = _.all(this.subHandles, function (handle) {
        return handle.ready();
    });

    return {
        subsReady: ready,
        people: People.find({}).fetch()
    }            
},
componentWillMount() {
    this.subHandles = [];
    this.subHandles.push(Meteor.subscribe('allPeople');
},
componentWillUnmount() {
    this.subHandles.map(function(handle) {
        handle.stop();
    });
}

Если он по-прежнему рендерится дважды, я бы посоветовал попробовать включить быстрый рендеринг для маршрута и проверить, возникает ли эта проблема.

person Patrick Hübl-Neschkudla    schedule 22.09.2015
comment
Это тоже не работает, Патрик! Я ценю усилия. Я буду работать над отключением более быстрого рендеринга и посмотрю, смогу ли я исправить это другим способом. - person Dan; 27.09.2015