Passing array via ReactiveVar in Meteor

僤鯓⒐⒋嵵緔 提交于 2020-01-05 05:01:21

问题


I have a Meteor method that returns all user accounts on my application

returnUsers: function(){
    return Meteor.users.find().fetch();
}

I'm using new ReactiveVar to pass the return value of the Meteor method into my template helper:

Template.listViewTemplate.created = function (){
    var self = this;
    self.myAsyncValue = new ReactiveVar("Waiting for response from serv er...");
    Meteor.call('returnUsers', function (err, users) {
        if (err)
            console.log(err);
        else 
            self.myAsyncValue.set(users);
    });
}

Template.listViewTemplate.helpers({
    userCollection: function(){
        return Template.instance().myAsyncValue.get();
    }
});

But when I go to render the users into the view, I get a console error that reads

{{#each}} currently only accepts arrays

When I render without the #each iterator, using

<ul id='usersList'>
    {{userCollection}}
</ul>

the output on my web-page accurately reflects the number of users (2), but reads

[object Object],[object Object]

I'm pretty sure that there is some funkiness going on here because I'm using a global Meteor collection (Meteor.users.find().fetch(), as opposed to having defined my own collection), but I'm not sure how to get around it.

I want to display a list of all users so the current user can click another user and share a document with them--not sure how to get around this.


回答1:


You don't need to use a reactive variable for this. The function at Template.listViewTemplate.created is not container in an autorun, which means: It won't get recomputed.

The best approach for your scenario is: Use a variable to get the status ( loading, loaded, error) and another variable to save the array itself attach to self. Reactivity is cool but you should only use it when needed.

About:

[object Object],[object Object]

This is happening because you're not extracting any value form the object provided nor looping using {{#each}}.

Your solutions for listing users is dangerous and inefficient. You're sending to the client all the fields from the user collection, including login tokens.

The best approach is to create a subscription that send only the necessaries fields like: _id, info.firstName. You should also have some criteria to the list users and use pagination. Consider also a search feature for such purpose.




回答2:


ReactiveVar doesn't like arrays. You could install the ReactiveArray package which should accomplish exactly what you want.

Update

Based on comment of mper

In the latest versions of Meteor you can put an array in a ReactiveVar.

Tested on

  • meteor@1.6.0
  • reactive-var@1.0.11



回答3:


I have several remarks about your question:

Do not fetch

You don't need .fetch() on your method. When you call find() on collections, such as Meteor.users a cursor is returned. The template (and #each in particular) can iterate through cursors. Cursors are usually better because you don't load the entire collection into memory at once - fetch does.

Meteor collections are reactive

Meteor collections are already reactive, meaning that if they change, they will trigger changes on your templates as well. So, you don't need to use a ReactiveVar to wrap your collection.

Query your local database

You don't need to use a method to get the users and in fact, you shouldn't, because usually you want to make queries to the database stored locally, not make calls to the server. Just call Meteor.users.find() directly in your template helper. You can (and should) control what is available locally through subscriptions.

Use #each with else

You can use the following in your template:

 {{#each userCollection}}
 ...
 {{else}}
 Waiting for response from server...
 {{/each}}

If userCollection is empty, the template will render the else block, just like you wanted.

Summarizing

Delete your method and onCreated with everything inside, change whatever is inside your template helper to only return Meteor.users.find() and use {{#each userCollection}}...{{else}}Waiting for response from server...{{/else}}

By the way

In the latest versions of Meteor you can put an array in a ReactiveVar.




回答4:


Template.onCreated(function(){}) only gets run once and meteor methods only run once

You need reactivity here.

Collections sre reactive meaning pub/sub.

You need to create a publish function that allows certain users to fetch other users in the database. So all uses with maybe if the currentUser has permission to read all user info. Id limit the fields too.



来源:https://stackoverflow.com/questions/29381734/passing-array-via-reactivevar-in-meteor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!