Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Meteor: Why am I losing my data context by switching function() { } to () => { }?

So I'm experimenting with ES6, installed the grigio:babel package, and am starting to go through my es5 code and update it to some of the new ES6 syntax when I ran into a problem.

Originally my template helpers looked something like this:

Template.exampleTemplateName.helpers({
   exampleHelper: function() {
      //returns an array from Mongo Collection
   }
});

which is used in a Blaze each loop as such

{{#each exampleHelper}}
{{/each}}

As you'd expect, all of my event handlers for the elements in this event loop had access to the fields in the Mongo Collection that is being returned by exampleHelper via the this keyword. this.exampleField would return exactly what I'd expect it to return.

So now's the point at which I started to update to ES6. For some reason the following syntax breaks the data context, so instead of this returning what you'd expect, it returns Window instead:

Template.exampleTemplateName.helpers({
    exampleHelper() {
        //returns an array from Mongo Collection
    }
});

The above was my first attempt, then I tried:

Template.exampleTemplateName.helpers({
    exampleHelper: () => {
        //returns an array from Mongo Collection
    }
});

So I ran the above ES6 code through Babeljs's online translator and received the following, which is obviously incorrect as I don't want a named function:

Template.exampleTemplateName.helpers({
     exampleHelper: function exampleHelper() {}
});

Can someone tell me what the correct syntax should look like?

like image 329
Kris Avatar asked Jul 03 '15 04:07

Kris


2 Answers

Can someone tell me what the correct syntax should look like?

Your original code was totally fine. You don't have to abuse the features and use them just in order to use them, save few keystokes, etc. In this case normal anonymous function is what you should use.

The reason why you have this confusion with this pointing to global object, is because this is how arrow functions work: they have lexical this, not dynamic. This means that this reference is bound statically to function context at the time of the function creation (in your case it was window), and not resolved dynamically at runtime.

like image 82
dfsq Avatar answered Nov 15 '22 00:11

dfsq


This code will not work (it will show the window object):

Template.homePage.helpers({
  exampleHelper: function () {
    return [
      {text: 'this'}, {text: 'that'}, {text: 'the other thing'}
    ];
  },

  process: () => {
    console.log(this);
  }
});

Because when you use => syntax, it wants to do something like this:

var self = this;

process(function () {
  doSomethingWith(self);
});

So in this case, this does indeed equal window. The solution is to not use => in this scenario.

like image 27
CaptSaltyJack Avatar answered Nov 14 '22 22:11

CaptSaltyJack