简体   繁体   中英

Firebase/React query for the user's name

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();
};

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) })

  1. Use 'post.name' as a reference to the user.
  2. Search in the 'users' collection the exact value that match that user id.
  3. Get 'username' value from the snapshot.

Hope it helps!

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM