Reputation: 1512
I'm trying to make my Post component work by getting the name of the user who posted it. Right now, the way it works is that I login with a user (through Google or using email/password combo) and I get the data of that user as auth.currentUser.displayName
or email, uid etc...
When I make a post, it takes the user's id which is the uid
because that is going to be unique.
Now, when I'm loading the posts I get the post.name
which was originally the user's name (until I changed it to store the uid
instead) but now I get the ID of the user....
So my question is: How can I get the user's name instead of the ID?
As you can see on the picture above, the name in the posts is the ID of the user. I want to get the username
of the user when displaying the posts. How can I do that?
I hope it makes some sense..
Here is my render() code:
render() {
const { message, posts, error } = this.state;
const isInvalid = message === '';
return (
<div>
<form onSubmit={this.onSubmit}>
<p>
Posting as:{' '}
{auth.currentUser.displayName || auth.currentUser.email}
</p>
<textarea
value={message}
onChange={event =>
this.setState(byPropKey('message', event.target.value))
}
name="message"
placeholder="Message..."
/>
<button disabled={isInvalid} type="submit">
Post
</button>
{error && <p>{error.message}</p>}
</form>
<div>
<ul>
{posts.map(post => (
<li key={post.id}>
<h4>{post.message}</h4>
<p>posted by: {post.name}</p>
{post.name === auth.currentUser.uid ? (
<button
type="submit"
onClick={() => {
database.ref(`/posts/${post.id}`).remove();
}}
>
Delete Post
</button>
) : null}
</li>
))}
</ul>
</div>
</div>
);
}
The way i'm displaying the posts:
componentDidMount() {
const postsRef = database.ref('posts');
postsRef.on('value', snapshot => {
let posts = snapshot.val();
let newState = [];
for (let post in posts) {
newState.push({
id: post,
name: posts[post].name,
message: posts[post].message
});
}
this.setState({
posts: newState
});
});
}
and the onSubmit:
onSubmit = event => {
const { message } = this.state;
db.doCreatePost(auth.currentUser.uid, message)
.then(() => {
this.setState({
message: '',
error: null
});
})
.catch(error => {
this.setState(byPropKey('error', error));
});
event.preventDefault();
};
Upvotes: 0
Views: 2004
Reputation: 598728
You'll need to do a client-side join of the user data. In it's simplest form this can be:
componentDidMount() {
const postsRef = database.ref('posts');
const usersRef = database.ref('users');
postsRef.on('value', snapshot => {
let posts = snapshot.val();
let newState = [];
for (let post in posts) {
usersRef.child(posts[post].name).once('value').then(function(snapshot) {
const username = snapshot.val().username;
newState.push({
id: post,
uid: posts[post].name,
name: username,
message: posts[post].message
});
this.setState({
posts: newState
});
})
}
});
}
Note that this code sets the state each time a user name is loaded, so you'll see many updates to the UI. If you want to reduce that number, look into Promise.all()
to wait for all reads. You'll also want to keep a cache of users you've already loaded, since right now the code loads a user for each post (even if a single user has many posts).
Upvotes: 1
Reputation: 940
You can get the username like this.
firebase.database().ref('/users/' + post.name).once('value').then(function(snapshot) {
const username = (snapshot.val() && snapshot.val().username)
})
Hope it helps!
Upvotes: 1