I am calling Meteor.user() in many helpers, one helper for each field with one call to Meteor.user()
Is that optimal? I mean is that fast? wont it cause unnecessary re-renders?
I am also calling the same helpers from other templates that inherit the helpers using the following
aldeed:template-extension package.
Template.Layout_protected.helpers({
userPicture() {
let user = Meteor.user();
return user && user.picture;
},
userFirstName() {
let user = Meteor.user();
return user && user.firstName;
},
userLastName() {
let user = Meteor.user();
return user && user.lastName;
},
userEmail() {
let user = Meteor.user();
return user && user.services && user.services.facebook && user.services.facebook.email;
},
userCreatedAt() {
let user = Meteor.user();
return user && ( user.createdAt.getDate() + '/' + (user.createdAt.getMonth()+1) + '/' + user.createdAt.getFullYear() );
},
languages() {
return _.keys(TAPi18n.getLanguages());
},
isActiveLanguage(language) {
return (TAPi18n.getLanguage() === language);
},
});
I think the the real question is if we call Meteor.user() multiple times in a page/component, then does Meteor optimize this function? for example get the data from cache or something.
so caching is limited to another function call on the current context. The database is used as a last resort. However, that still means a minimum of three call stacks each time Meteor.user() is called.
It is actually quite simple to optimize your code here. Since the accounts package already includes the default {{currentUser}} helper you can use it inside of a {{#let}} or {{#with}} for cacheing. This will work great if you just want to access the properties on the user record. For other methods where you need to compute a value based on those values you can create helpers that take the user as an argument and return this data, but my preferred method is to have the users collection return User models that have these methods defined on them.
If you would like to go the Model route, I highly recommend my package socialize:user-model.
This will require a little more work, but really pays off in the long run.
import { User } from 'meteor/socialize:user-model';
import SimpleSchema from 'simpl-schema';
// Attach new fields to the schema since socialize:user-model has already attached a schema
User.attachSchema(new SimpleSchema({
firstName: {
type: String,
},
lastName: {
type: String,
},
picture: {
type: String,
},
}));
// Add the methods we need onto the User class
User.methods({
fullName() {
return `${this.firstName} ${this.lastName}`;
},
email() {
return this.services && this.services.facebook && this.services.facebook.email;
},
createdDate() {
return `${this.createdAt.getDate()}/${user.createdAt.getMonth()+1}/${user.createdAt.getFullYear()}`;
},
});
There are also two Spacebars built-in helpers, {{#each}}, and {{#with}}, which we do not recommend using (see prefer using each-in). These block helpers change the data context within a template, which can be difficult to reason about.