Why does not working this ReactiveVar?


#1

I want to reflect in view, data from server.

When running onCreated, declare ReactiveVar instance variable and invoke server side method by Meteor.call, and set data to ReactiveVar instance variable in Metelr.call’s callback.

Then, get ReactiveVar instance variable and reflect view in helper method.

In the following cases,
onCreated -> autorun -> Meteor.call -> show -> callback -> show

I would like to operate in the order, but the last show method doesn’t work despite setting defferent value in callback.

please give me some advice…

# page.js
Template.page.helpers({
    getData(){
        return Template.instance().count.get();
    }
});

Template.page.onCreated(function() {
    this.count = new ReactiveVar(0);

    Tracker.autorun(() => {
        Meteor.call('serverMethod', (error, users) =>{
            let count = this.count.get();
            for( user of users){
                count++;
            }
            this.count.set(count) //set number other than 0.
        });
    });
});

# page.html
<span class="data">Data: {{getData}}</span>

#2

I think you’ve inadvertently used Template Intance data, which is read-only. Try replacing data with result or similar:

# page.js
Template.page.helpers({
    getData(){
        return Template.instance().result.get();
    }
});

Template.page.onCreated(function() {
    this.result = new ReactiveVar(0);

    Tracker.autorun(() => {
        Meteor.call('serverMethod', (error, data) =>{
            this.result.set(data) //set number other than 0.
        });
    });
});

#3

Thank you for the advice,

but sorry, I wrote “data” as an example, Actually the instance variable is “count”, and the argument of callback is “user”…

However, in this case should it work correctly if the variable name is normal?


#4

It should, unless your template isn’t called “page”:

<template name="page">
  <span class="data">Data: {{getData}}</span>
</template>

Also, I see you’ve corrected your code and added more in the autorun, which now looks somewhat dangerous to me: geting and setting the same reactive variable in an autorun can result in an infinite loop:

An autorun will always run the “enclosed” code once, and will re-run it if a dependent, reactive variable changes.

In your case, the dependent, reactive variable is count: you will re-run the autorun every time you do this.count.set(count) with a different value of count.

As a first step, try removing the autorun - it’s not needed here anyway:

Template.page.onCreated(function() {
    this.count = new ReactiveVar(0);

    Meteor.call('serverMethod', (error, users) =>{
        let count = this.count.get();
        for( user of users){
            count++;
        } // if users is an array you could do count += users.length in place of this loop
        this.count.set(count) //set number other than 0.
   });
});

Oh - you did do meteor add reactive-var to your project?


#5

Thank you, I was concerned about the infinite loop problem as well. However, it was postponed as “I made it to work first.”

and I probably added

meteor add reactive-var

because I developing Open source software now, ReactiveVar is used in another place.

I rewrote it as follows, but it still did not work…

Template.page.helpers({
        getCount(){
                console.log("getCount");
                return Template.instance().count.get();
        }
});


Template.page.onCreated(function() {
        this.count = new ReactiveVar(0);
        console.log("onCreated");

        Meteor.call('serverMethod', id, true, (error, users) => {
                console.log("callback");
                let count = this.count.get();
                count += users.records.length;
                console.log(count); // output: 2
                this.count.set(count);
        });
});

This code is repeatedly executed by forEach.And looking at the log of the above code, it looks like the following.

onCreated
getCount
onCreated
getCount
onCreated
getCount

callback
2
callback
2
callback

Is it related to having callback method executed at the same time after all processing is finished?


#6

I don’t see a forEach. That behaviour doesn’t seem to make sense. Can we see your HTML template(s) please?


#8

Good afternoon, rabfallows.

The invoker source are as follows.

invoker html

    {{#each createPages}}
        {{#nrr nrrargs 'page' .}}{{/nrr}}
    {{/each}}

invoker js

createPages() {
		# create query and options
		const pageObj = PageCollection.find(query, options);
		return pageObj
	},

pageObj contain twenty page objects and more.

And after all that is over, the Meteor.call callback comes back.

Do you think it anything to do with it?