ReactiveVars in subscriptions with FlowRouter


#1

Just playing around and attempting to port the Microscope example from Iron Router to Flow Router. I am trying to work on the “Load More” feature at the moment, and ran into an issue. Any time a ReactiveVar would get updated, this error message would appear in the console;

Error: You can't use reactive data sources like Session inside the '.subscriptions' method!

The code that I am using is simply:

subscriptions: function(params, queryParams) {
    if(Meteor.isClient) {
      this.register('posts', Meteor.subscribe('posts'),  Limit.get());
    }
}

Note that for now, I am just using a ReactiveVar to control the page limit instead of reading from the query. But when the button gets clicked to increase the page limit, that error message gets displayed.

Now, I know that FlowRouter isn’t reactive like IronRouter by design, but I figured that since subscriptions support reactive values, this would be possible.

Should this be possible with FlowRouter? Am I doing something wrong? If this is expected behavior is, is there a pattern to use Flow Router and reactive subscriptions together?

Thanks everyone,

Mike


#2

I think you would need to have the load-more button event do the re-subscribing and not try to rely on the route state updating the subscription…


#3

Hi, try this example.

Meteor Pattern: Template-Level Subscriptions


#4

Here you are using a reactive content on the router. That’s why give you an error. We are pretty strict in that.

May be you need to send the limit via the URL via either using a param or via a queryString.
See this article: https://meteorhacks.com/meteor-ui-pattern-keeping-app-state-in-the-url


#5

If you really really like to use the ReactiveVar. Use like this. But I don’t recommend it.

subscriptions: function(params, queryParams) {
    if(Meteor.isClient) {
      var limit = Tracker.nonreactive(function() {
        return Limit.get();
      });
      this.register('posts', Meteor.subscribe('posts'), limit);
    }
}

#6

I agree with Arunoda. I am migrating away from IronRouter because it allows you to do so much reactive stuff in the routes. One of the pros of FlowRouter is that it’s very simple, you hit a route and load a template. This makes the router layer very easy to maintain.

In a small app having reactive subs in the router seems like a great idea, but it has always come back to bite me sooner or later. The article @nxcong linked to is a far better way. I’m refactoring my subscriptions and reactive data out of the router and into the template level and it’s made debugging easier and has reduced bugs.


#7

Thank you for the feedback everyone.

I’m going to try both template level subscriptions and keeping the state in the URL to see which one works better and feels nicer (at least for this example).

Maybe I’ll have an example worth showing off in the future!


#8

Yea let us know how it works! Also, you can still store state in the URL when using template level subscriptions. I do this a lot to enable the user to bookmark the page or copy/paste the link and that allows everything to rebuild based on the URL.

Basically the route can have params or query params for the data your app needs (limit, offset, etc…) and when the top level template loads (let’s call it ‘FeedList’), it will look at the current params (using FlowRouter API) and then it will setup it’s subscription based on those params. To increase the limit you can update those params (with FlowRouter API) and the subscription will update itself reactively!

With this scenario your router is only responsible for loading your ‘FeedPage’ template and then your ‘FeedList’ child template can be responsible for changing the data it needs.

To illustrate how helpful this is in a more complex app, say your ‘FeedPage’ (imagine the Facebook feed if it helps) would have 3 child components… ‘FeedList’, ‘ChatList’, and ‘TrendingList’. Each of these have separate subscriptions and it’s very easy to see where the data is coming in from.

If you need further organization because your top level ‘FeedList’ template/script is getting too complex, you can create a parent template called ‘FeedDataContainer’ who’s only responsibility is fetching data and rendering it’s single child, the ‘FeedList’ template. It would pass this data down into ‘FeedList’.

This may be overkill on a small app but makes things more re-useable in a large app. (for instance if a ‘comment’ template get’s it’s data from a parent, not directly, it makes it easy to use this ‘comment’ in a feed item, photo item, etc… This is something i’ve learned from React but it works quite well in Blaze as well.


#9

@arunoda this https://meteorhacks.com/meteor-ui-pattern-keeping-app-state-in-the-url example only get the parameters from the URL and use in the client or maybe i missed something

how about using the parameters and use it the Meteor.publish in the server?

The reason I ask because I would like to use my code below into FlowRouter

Meteor.subscribe("pharmaWithStocks",
    Session.get("searchMedDist"),
    Session.get("setLng"),
    Session.get("setLat")
);

Thanks for the help


#10

I hope you are trying to use the .subscriptions method in the flow-router. If so, try to send the parameters from the URL. If you can’t try to save it on normal variables.

If you really needs to use session variables. Use this inside Tracker.nonreactive


#11

I ended up using the parameters from the URL and use FlowRouter.getQueryParam to pass pass it to my Meteor.subscribe function.

Thanks.