Proposal feedback: Deprecating Session in favor of ReactiveDict

Hi guys!

In my product research talking to various poeple, I’ve found that a lot of people have been burned by using Session. Their data ends up pretty much global and it’s hard to keep track of what parts of your app are coupled together.

To fix that, I’ve come up with this idea, which basically boils down to deprecating Session and having people instantiate their own ReactiveDict instances (Session is just a single instance of ReactiveDict).

Check it out: https://meteor.hackpad.com/Proposal-Deprecate-Session-in-favor-of-ReactiveDict-0wbRKtE4GZ9

Please comment!

1 Like

I’m all for this. I would also love to see deprecation of the profile field on the users collection.

1 Like

It’s in progress! Here’s the branch: https://github.com/meteor/meteor/tree/deprecate-profile

I’m starting by making it read-only by default (for the case where people sometimes do something like user.profile.isAdmin) and then maybe at a later date we will make it disappear completely.

1 Like

How would you propose someone send reactive data from one template to another? ReactiveVar/ReactiveDict are not global.

You can make them global.

The implementation of Session in terms of ReactiveDict is:

Session = new ReactiveDict("session")

It’s very easy to declare a global variable in Meteor (maybe even too easy)

2 Likes

I like the idea. It’s pretty difficult to build and maintain a state machine with Sessions being global.

I’m confused. Why are they bummed? Nothing is stopping anyone from using their own reactive vars and dicts. I wouldn’t consider this a new feature. It’s just a pattern or convention. Perhaps the Meteor docs should give more examples on how to use reactive template variables on template instances.

But Session should indeed just be gotten rid of. The assumed replacement would just be manual use of reactive vars and dicts.

The more I think about it, the more weird it seems to automatically instantiate the Session on every app. It’s like automatically instantiating count = 0, and then calling that a feature. I like the idea of deprecating Session and having people conjure reactive dictionaries at their own discretion.

I don’t know if I agree with deprecating Session. I don’t see the issue. If people are having namespacing issues, that’s not the fault of Session. One could be smarter about this, by naming things carefully, e.g.:

Session.set('buyer/location', currLoc);
Session.set('buyer/isSomeValue', true);
Session.set('admin/someValue', 'abc');

If Session is simply a global ReactiveDict, what’s the point of getting rid of it? If I wanted to share data between two templates, I’d still wind up using a global variable to do so, as using an unmanaged local collection seems overkill just to keep track of states.

2 Likes

True, if it was deprecated, I would create it anyways if I needed it.

The session is such a simple thing that it might be unnecessary to create it in every project. But there’s a much bigger point. The bigger point is to teach people how not to rely on session if they don’t have to. This is a good purpose for not including the Session as default, right?

So, if someone wants to include it in their project, then they can do it actively, rather than passively. Like you stated, it’s a small or non-existent issue on a per-project scale and I don’t personally mind if it is or isn’t deleted.

But for beginners, it might be better to not include it, and teach a much more general usage of reactive variables and dictionaries, which will be more useful in the long run.

2 Likes

I’m still wondering, without polluting the global namespace, and without using an unsynchronized local collection, how does one communicate a variable from one template to another? Because I think that will become the main question, if it’s recommended that we do a way with global reactive variables.

<template name="main">
  <input id="user-input">

  <div>
    {{> other}}
  </div>
</template>

<template name="other">
  {{someVar}}
</template>
Template.main.onCreated(function () {
  this.someVar = new ReactiveVar();
});

Template.main.events({
  'keyup #user-input': function (event) {
    var txt = $(event.target).val();

    Template.instance().someVar.set(txt);
  }
});

Template.other.helpers({
  someVar: function () {
    return <the someVar reactive var from the 'main' template>;
  }
});

Well, one way would be to put those templates into a package. Then, if you don’t export that ReactiveDict from the package, you know that only the code inside the package can access it.

5 Likes

That is interesting …

I’ve just been doing things like {{#with extend this … }} (or similar)

From a newbie perspective, I am all for it. I’ve just recently learned, to my great surprise, that sessions live on the client and are not therefore sessions per se in the way many people are used to the concept. IMHO, ReactiveDict would make this fact explicit and self documenting, among other things.

Imho it’s not a good thing to use session variables in the default example (leaderboard).
It may lead to bad habits from day 0.

1 Like

You could also build up a custom object and pass that along with a {{#with}}. There is also a way to access a parents data context:
http://docs.meteor.com/#/full/template_parentdata

I have had problems getting this to work though.

EDIT: I am all for getting rid of Session variables or at least make them not seem as “fundamental” as e.g. the leaderboard example or a host of other tutorials are do. Meteor is a bane and a blessing for beginners since “Everything goes” makes it easy to build something but also insanely hard to know HOW to make something go properly.

Yeah, I’m not too familiar with the package inclusion process; I also use that technique.

It might be nice for Meteor to ship with a nice way to easily tack stuff, on the fly, onto the this or .., etc. variables in a template. I found it useful to wrap _.extend as a global template helper, so I can quickly tack on additional properties into “this”, or “…” for parent, etc.

The package inclusion technique that @sashko mentioned seems like a more compact way to accomplish it though!

I feel that those tutorials use it because it is a very simple way to illustrate reactivity without cooking an entire pot of spaghetti in the tutorial. I still use Session extensively though, just not for anything intra-template. When it comes to inter-template stuff, I try to design the templates in such a way that {{#with}} can save the day, but it seems like that deign pattern can quickly become limiting. I guess my usage doesn’t require (yet) this capability to a large enough extent where {{#with}} wouldn’t work…

Another way to get around that problem is by doing certain things at the outer-most template’s level (e.g. layout code), which can act as a common pathway for all the templates. Again, though, I am not sure if that’s the best practice.