5

I am having some trouble getting all the registered users to display on the client side. std:accounts-ui package is included in .meteor/packages. autopublish package has been removed.

The data for all users are published in Users.js as allUsers, while the client subscribes to the allUsers publication from within createContainer provided by react-meteor-data.

However the page only renders the details of the user that is currently logged in. Running Meteor.users().find().fetch() in the browser JS console only shows the currently logged in user, and shows nothing if the user is not logged in.

Running console.log(Meteor.users.find().fetch() on the server side outputs all the users correctly.

Why is this happening on the browser?

/imports/api/Users.js

import { Meteor } from 'meteor/meteor';

if (Meteor.isServer) {
    Meteor.publish('allUsers', function() {
        return Meteor.users.find({});
    })
}

/imports/ui/App.jsx

import React, { Component, PropTypes } from 'react';
import { createContainer } from 'meteor/react-meteor-data';
import { Accounts } from 'meteor/std:accounts-ui';
import { Table } from 'react-bootstrap';
import User from './User';


export class App extends Component {

    renderUsers() {
        return this.props.users.map((user) => (
            <User key={user._id} user={user} />
        ));
    }


    render() {
        return (
            <div>
                <h1>Users</h1>

                <Table>
                    <tbody>
                        <tr>
                            <td>ID</td>
                            <td>Email</td>
                            <td>createdAt</td>
                        </tr>

                        { this.renderUsers() }

                    </tbody>
                </Table>
            </div>
        )
    }
}

App.propTypes = {
    users: PropTypes.array.isRequired
}

export default createContainer(() => {
    Meteor.subscribe('allUsers');

    return {
        users: Meteor.users.find().fetch()
    }
}, App);

/imports/ui/User.jsx

import React, { Component } from 'react';

export default class Users extends Component {
    render() {
        return (
            <tr>
                <td>{ this.props.user._id}</td>
                <td>{ _.get(this.props, 'user.emails[0].address', 'UNKNOWN') }</td>
                <td>{ this.props.user.createdAt }</td>
            </tr>
        )
    }
}
Nyxynyx
  • 61,411
  • 155
  • 482
  • 830
  • 1
    Upvote for using plural "are" for data. – Jonathan Wheeler Dec 19 '16 at 05:30
  • @JonathanWheeler omg thank you!!! :) – Nyxynyx Dec 19 '16 at 05:31
  • Meteor.user() I know is a built in function. Can you still access your function that you describe here if you do not subscribe to allUsers? – Jonathan Wheeler Dec 19 '16 at 05:32
  • @JonathanWheeler Yes it can still be accessed in the browser JS console if not subscribed – Nyxynyx Dec 19 '16 at 05:34
  • That may be the problem. You might be trying to overload a built in function. This has been a pain in the neck for me whenever I build Meteor apps – Jonathan Wheeler Dec 19 '16 at 05:35
  • @JonathanWheeler I followed the [solution to this SO question](http://stackoverflow.com/questions/13151879/publish-certain-information-for-meteor-users-and-more-information-for-meteor-use). It publishes `Meteor.users.find()` and subscribes to this. – Nyxynyx Dec 19 '16 at 05:36
  • That's about all the help I can give them. I always got stuck at things like this myself. – Jonathan Wheeler Dec 19 '16 at 05:38
  • Strange. Your code looks exactly correct. What happens if you open up the console of your browser and type `Meteor.subscribe('allUsers')` followed by `Meteor.users.find().fetch()`? What do you see? – ffxsam Dec 19 '16 at 07:44
  • @ffxsam From the console output of `Meteor.users.find().fetch()`, I still see only the currently logged in user... – Nyxynyx Dec 19 '16 at 17:13
  • Strange. What if you put a `console.log` statement inside your publish function? Is the publish function actually getting called? – ffxsam Dec 19 '16 at 18:26
  • PS: I would take the answer below with a grain of salt. I think there's something else wrong going on in your code, because you absolutely should be able to publish all users. I'm doing this in two projects of mine. – ffxsam Dec 19 '16 at 18:27
  • @ffxsam Yes the publish function is being called, added `console.log` into the callback function of `Meteor.publish`.... – Nyxynyx Dec 20 '16 at 00:28
  • 1
    @ffxsam, just solved the problem. I had `import User from './User';` but was exporting `Users` instead of `User`. That somehow messed up the publication subscription. Finally solved!! – Nyxynyx Dec 20 '16 at 00:36
  • 1
    @Nyxynyx Glad to hear! :) – ffxsam Dec 20 '16 at 05:12
  • 1
    @Nyxynyx Glad to hear you have solved your problem :). I think my answer works only for angular2-meteor. React may have different way of publishing. i have checked it on 14.4 Create Users collection from Meteor.users of https://angular-meteor.com/tutorials/socially/angular2/using-and-creating-angularjs-pipes angular2-meteor official tutorial.You can check. For angular you actually have to create a collection. I though it would work for React also. Anyway i was just trying to help – Amit kumar Dec 20 '16 at 05:32
  • 1
    @AmitSuhag Thanks so much for your help!! – Nyxynyx Dec 20 '16 at 06:28

1 Answers1

2

i have faced the same problem when i was using angular 2 and meteor. i also tried to accesss data using Meteor.users.find({});

but this is not the correct way to use. for using this first you should create a new collection like this

export const Users = MongoObservable.fromExisting(Meteor.users);<-- most important line

then in

Meteor.publish("userData", function() {
        if (Roles.userIsInRole(this.userId, 'admin')) {
            return Meteor.users.find();
        } else {
            const selector = {
                '_id': this.userId
            };
            return Meteor.users.find(selector);
        }
    });

and use in your file by subscribe to it.

MeteorObservable.subscribe('userData').subscribe(() => { 
                     this.userlist=Users.find({});      
            });

i did it in angular 2.you plz use react syntax for last subscribe part.

Amit kumar
  • 6,029
  • 6
  • 30
  • 40
  • I tried `import { Meteor, MongoObservable } from 'meteor/meteor';` and `const Users = MongoObservable.fromExisting(Meteor.users);` but got the error `Uncaught TypeError: Cannot read property 'fromExisting' of undefined` in the browser console. – Nyxynyx Dec 19 '16 at 06:16
  • 1
    Do I need to install any packages to access `MongoObservable`? Such as https://www.npmjs.com/package/meteor-rxjs or is it now built into Meteor? – Nyxynyx Dec 19 '16 at 06:17
  • you don't have to use MongoObservable. In react meteor there should be a method for creating a collection from existing. first try using export const Tasks = new Mongo.Collection(Meteor.users); I never used react so can't tell you exactly but there should be some way. – Amit kumar Dec 19 '16 at 06:48
  • 1
    @Nyxynyx actually meteor automatically create a users collection for Meteor.users if you have seen you mongodb. you just have to use that collection. for that either you create a new collection which will be copy of you default users collection using new Mongo.Collection(Meteor.users); or you can directly subscribe to you monogdb users collection. – Amit kumar Dec 19 '16 at 07:21