ujcorb
July 31, 2018, 10:13am
1
I want to create a table to display all my users. I use the account-ui package
of Meteor to create new users.
However, It simply returns an empty object when I call my users in my React component. Is there something I forgot ? like an import maybe ?
imports/api/users.js
is used to Publish:
import { Meteor } from 'meteor/meteor';
if (Meteor.isServer) {
Meteor.publish('users', function() {
return Meteor.users.find({});
})
}
then I call my component and make use of withTracker
in which I subscribe:
import React from 'react';
import { Mongo } from 'meteor/mongo'
import { withTracker } from 'meteor/react-meteor-data';
class CollectionTable extends React.Component {
render() {
return (
<table className="table table-hover table-responsive">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
{this.props.users.map(u => {
<tr>
<th scope="row">{u._id}</th>
<td>{u.profile.firstname}</td>
<td>{u.profile.lastname}</td>
<td>{u.profile.phonenumber}</td>
</tr>
})}
</tbody>
</table>
);
}
}
export default withTracker(() => {
Meteor.subscribe('users');
return {
users: Meteor.users.find().fetch()
};
})(CollectionTable);
minhna
July 31, 2018, 10:23am
2
You have to wait until the subscription is ready.
export default withTracker(() => {
const sub = Meteor.subscribe('users');
if (sub.ready()) {
return {
users: Meteor.users.find().fetch()
};
}
return { users: [] };
})(CollectionTable);
1 Like
ujcorb
July 31, 2018, 10:29am
3
hi minhna,
Thank you very much for your help,
So I added your suggestion but it does not seem to change anything. Just to observe the ouput, I ran this:
componentDidMount() {
console.log(this.props.users)
}
that prints an empty array. Don’t know why
ujcorb
July 31, 2018, 11:14am
4
OK so I don’t know why this now works but I solved it doing this:
import React from 'react';
import { Mongo } from 'meteor/mongo'
import { withTracker } from 'meteor/react-meteor-data';
export class CollectionTable extends React.Component {
componentWillReceiveProps(newProps) {
console.log(newProps); // i get the right data!
console.log(this.props); // empty array >_<
}
renderUsers() {
return this.props.users.map(u => (
<tr key={u._id}>
<th scope="row">{u._id}</th>
<td>{u.profile.firstname}</td>
<td>{u.profile.lastname}</td>
<td>{u.profile.phonenumber}</td>
</tr>
));
}
render() {
return (
<table className="table table-hover table-responsive">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">First</th>
<th scope="col">Last</th>
<th scope="col">Handle</th>
</tr>
</thead>
<tbody>
{this.renderUsers()}
</tbody>
</table>
);
}
}
export default withTracker(() => {
const sub = Meteor.subscribe('users');
if (sub.ready()) {
console.log(Meteor.users.find().fetch());
return {
users: Meteor.users.find().fetch()
};
}
return { users: [] };
})(CollectionTable);
I left my console.log for debugging purposes if ever someone can explain why this.propsgives an empty array, because it is still a mystery for me.
It works perfectly though !
minhna
July 31, 2018, 12:03pm
5
At first, when componentDidMount
called, the users props is empty because the subscription has not ready yet.
After that, when the subscription ready, the users props changed, componentWillReceiveProps
called with new (updated) props, and the render
method will be called (again) after that.
1 Like
Do not use componentWillReceiveProps
as it is marked as deprecated (to be removed in React 17). In this case, use getDerivedStateFromProps
instead
2 Likes