Yanick Rochon
Yanick Rochon

Reputation: 53616

Subscriptions with react-meteor-data

From the docs, I wrote my container like so

export default InventoryItemsList = createContainer(() => {
  const itemsCollection = Meteor.subscribe('allInventoryItems');
  const loading = !itemsCollection.ready();

  return {
    loading,
    items: !loading ? InventoryItems.find().fetch() : []
  };
}, class InventoryItemsListComponent extends Component {
  render() {
    let items = this.props.items;

    /* some render logic */

    return /*... react component template ...*/ ;
  }
});

The problem I see is that

  1. The container function is executed many times, thus calling Meteor.subscribe more than once; is that good? Will Meteor just ignore subsequent subscriptions?
  2. According to this tutorial, subscriptions need to be stopped, but the docs do not mention it at all. This does not take care on it's own, does it?

What is the recommended way to stop (i.e. unsubscribe) or resolve the 2 issues that I see from that point?

Is TrackerRact actually better? (yes, I know this is opinionated, but surely there is some form of a convention with meteor react, here!)

Upvotes: 0

Views: 820

Answers (2)

rafahoro
rafahoro

Reputation: 1257

About your problem 2), this is how I solve it

1- When you subscribe to something, store those subscriptions references and pass them to the component.

Here an example with 2 subscriptions, but subscribing to only 1, is even easier.

createContainer((props) =>{
  const subscription = Meteor.subscribe('Publication1', props.param1);
  const subscription2 = Meteor.subscribe('Publication2', props.param1, props.param2);
  const loading = !(subscription.ready() && subscription2.ready());
  const results1 = loading ? undefined : Collection1.find().fetch();
  const results2 = loading ? undefined : Collection2.findOne({a:1});
  return {subscriptions: [subscription, subscription2], loading, results1, results2};
}, MyComp);

Then in my component:

class MyComp extends Component {
......
  componentWillUnmount() {
    this.props.subscriptions.forEach((s) =>{
      s.stop();
    });
  }
....
}

This way, the component will get in props.subscriptions all the subscriptions it needs to stop before unmounting.

Also you can use this.props.loading to know if the subscriptions are ready (of course, you can have 2 different ready1 and ready2 if it helps).

Last thing, after subscribing, if you .find(), dont forget to .fetch(), else the results will not be reactive.

Upvotes: 0

Mabeh Al-Zuq Yadeek
Mabeh Al-Zuq Yadeek

Reputation: 84

1) The container component is a reactive component, so whenever documents are changed or added to the given collection, it's going to call via your container and update the DOM.

2) As far as I know, the container will only subscribe to the collection via the actual component you bind it to. Once you leave that component, the subscriptions should stop.

If you want to unsubscribe directly, you can just call this.props.items.stop() in your componentWillUnmount() method.

Finally, I will have to say that using React specific implementations are always better than using Meteor specific functions (i.e. it's always better to use state variables over Sessions with React, as it's always better to use containers than Tracker.autorun() with React, etc, etc).

Upvotes: 1

Related Questions