Multiple Subscription using withTracker

Hi everyone,

I am building an App in which I need to load data from two different collections: Meals and Restaurants.

So I tried the code below:

export default withTracker(() => {
  const sub1 = Meteor.subscribe('meals');
  const sub2 = Meteor.subscribe('restaurants');
  const today = new Date();
  if (sub1.ready() && sub2.ready()) {
    return {
      meals: Meals.find({weekDay: today.getDay().toString()}).fetch(),
      restaurants: Restaurants.find().fetch()
    };
  }
  return { meals: [], restaurants: [] };
})(App);

it actually returns meals as expected but not the restaurants (returns the default empty array)

Is there something wrong with my code here or does the problem come from another piece of code ? (that I’ll post here if necessary)

Have a good day,

Julien

If it’s returning meals, then it must be executing the main return and not the default return. Maybe check your restaurants publication?

Hi @robfallows, thank you for your answer,

What I meant by this is that the meals are returned as expected (I get the 4 meals I am supposed to get when using this.props.meals) but that should be the same for my restaurants although I get the default value when using this.props.restaurants.

Publications are identical for both:

if (Meteor.isServer) {
    Meteor.publish('meals', function() {
        return Meals.find({});
    })
}
if (Meteor.isServer) {
    Meteor.publish('restaurants', function() {
        return Restaurants.find({});
    })
}

Ok my bad I found out the problem. However there is still something I don’t get.

so I have this method renderMap() where I call (console.log(this.props.restaurants)).

Then I call it in render() like so:

<div>
  {this.renderMap()}
</div>

but the methods seems to run twice: I get first the default value, and then the right values. why ?

Tracker methods can run multiple times. They always run once, and they they re-run whenever any reactive dependencies within change. So your defaults will be on the first run, when the subscriptions are most likely not yet ready. When they become ready, it will re-run.

1 Like

Thank you ! @robfallows ! So then how can I avoid the first loading, which only returns the default value (empty array) ? It causes me lots of headache with other stuff…

Hmm. You can’t avoid it - it happens. The best you can do is code around it, often by using guards: you did with if (sub1.ready() && sub2.ready()).

There’s some useful info on Tracker itself (which is used in withTracker) here and here, which may be helpful in understanding the flow.

There’s also the section on withTracker in the Meteor Guide which deals with preventing re-renders.

1 Like