【问题标题】:React and Firestore - problem with retrieving the user profile picture URLReact 和 Firestore - 检索用户个人资料图片 URL 的问题
【发布时间】:2020-07-15 00:28:24
【问题描述】:

所以当我用户发表评论时,我正在考虑将他们的个人资料图片 URL 存储在评论对象上,以便我可以轻松访问它,但我认为这不会奏效,因为如果他们更改他们的个人资料图片或删除它,评论仍将包含他们的旧 URL,我也尝试将对用户的引用存储在 Firestore 中,但我不确定是我做错了还是什么,因为我一直遇到错误。

TLDR - 我在问是否有人知道存储和访问特定评论的 URL(将来可能会改变)的方法。

对不起,如果我没有澄清或解释事情,我对 React 很陌生,你可能已经知道了。如果有人有任何问题,我可以尝试更好地解释事情,所以是的,感谢您阅读本文并提前感谢。

import React, { useEffect, useState } from 'react';
import { postComment, deleteComment } from '../../store/actions/commentsActions';
import { connect, useSelector } from 'react-redux';
import { useFirestore } from 'react-redux-firebase';
import { useForm } from 'react-hook-form';
import { toast } from 'react-toastify';
import moment from 'moment';
import { ErrorCircle } from '@styled-icons/boxicons-solid/ErrorCircle';
import { Error } from  '@styled-icons/boxicons-solid/Error';

import { Modal } from '../../helpers/Modal';
import ProfilePlaceHolder from '../../assets/images/user.svg';

import Loading from '../../helpers/Loading';

export const Comments = (props) => {

    const { auth, match, history, commentError } = props;
    const slug = match.params.slug;
    const firestore = useFirestore();
    const profile = useSelector(state => state.firebase.profile);

    const { register, handleSubmit, reset } = useForm();

    const [comments, setComments] = useState([]);
    const [loading, setLoading] = useState(true);

    useEffect(() => {

        const listener = 
        firestore
        .collection('posts')
        .doc(slug)
        .collection('comments')
        .orderBy('createdAt', 'desc')
        .onSnapshot((snapshot) => {
            let _comments = [];
            snapshot.forEach(commentSnapshot => {
                const thisComment = commentSnapshot.data();
                _comments.push({commentData: thisComment, commentId: commentSnapshot.id});
            });
            setComments(_comments);
            setLoading(false);
        }, (error) => {
            console.log(error);
        });

        return () => listener();

    }, [firestore, slug]);

    const postComment = async (formData) => {

        if (auth.isEmpty) {
            toast.error('You are not authenticated ????');
            return;
        }
        await props.postComment({formData, slug});
        reset();
    };

    const deleteComment = (commentId, authorId) => {

        const currentUserId = auth.uid;
        const commentUserId = authorId;

        if (!comments) {
            return;
        }

        if (currentUserId !== commentUserId) {
            toast.error('That\'s not your comment')
            return;
        }

        props.deleteComment({commentId, authorId, slug});  
    };

    const back = () => {
        history.goBack();
    };

    if (loading) {
        return <Loading />;
    };



    return (
        <div className='main' style={{ width: '600px', maxWidth: '90%' }}>
            { 
                commentError !== null ? (
                <span className='error-message'>
                    <ErrorCircle size='30' style={{ marginRight: 5 }} />
                    {commentError}
                </span> ) : null
            }
            <div className='long-container' onClick={back} style={{ cursor: 'pointer', height: '50px' }}>
                Commenting on the post: {slug}
            </div>
            <div className='long-container' style={{ padding: '10px 0' }}>
                <div>
                    <img 
                        src={profile.profilePictureURL ?? ProfilePlaceHolder} 
                        alt='Profile' 
                        className='profile-picture' 
                    />
                    <span className='usertag-span'>{auth?.displayName}</span>
                </div>
                <div>
                    <form onSubmit={handleSubmit(postComment)}>
                        <textarea 
                            name='content'
                            rows='3' 
                            disabled={!auth}
                            style={{ margin: '10px 0' }}
                            placeholder='Add to the conversation!'
                            ref={register({ required: true })}
                        /> 
                        <span style={{ width: '90%' }}>
                            <button>Comment</button>
                        </span>
                    </form>
                </div>
            </div>
            {comments.map((comment) =>
            <div key={comment.commentId} className='long-container' style={{ padding: '15px 0' }}>
                <div style={{ height: '30px' }}>
                    <img 
                        src={comment.commentData.authorProfilePicture ?? ProfilePlaceHolder} 
                        alt='Profile' 
                        className='profile-picture'
                    />
                    <div className='commentMetadata' style={{ flexDirection: 'column', alignItems: 'flex-start', justifyItems: 'center' }}>
                        <span className='usertag-span'>{comment.commentData.author}</span>
                        <span>{moment(comment.commentData.createdAt?.toDate()).fromNow()}</span>
                    </div>
                </div>
                <span className='commentText-span'>
                    {comment.commentData.content}
                </span>
                <span className='commentText-span' style={{ justifyContent: 'flex-end' }}>
                    { 
                        auth.uid === comment.commentData.authorId ?
                        (
                            <Modal 
                                buttonActionClassName='delete-button' 
                                visibleButtonClassName='delete-button'
                                modalContentHeaderBackgroundColor='#fa4949'
                                title='Confirm' 
                                modalContent='Are you sure you want to delete this comment?' 
                                emoji={<Error size='30' color='#f53d3d' style={{ marginRight: 10 }} />}
                                buttonActionName='Delete'
                                buttonAction={() => deleteComment(comment.commentId, comment.commentData.authorId)}
                            />
                        ) : null
                    }
                </span>
            </div>
            )}
        </div>
    )
}

const mapDispatchToProps = (dispatch) => {
  return {
    postComment: (comment) => dispatch(postComment(comment)),
    deleteComment: (commentToDelete) => dispatch(deleteComment(commentToDelete)) 
  }
} 

const mapStateToProps = (state) => {
    return {
        auth: state.firebase.auth,
        commentError: state.commentsReducer.commentError,
    }
} 

export default connect(mapStateToProps, mapDispatchToProps)(Comments);

这也是我尝试过的,我提到过,但并没有完全奏效,呵呵

    useEffect(() => {

        const listener = firestore
        .collection('posts')
        .doc(slug)
        .collection('comments')
        .onSnapshot((snapshot) => {
            let _comments = [];
            snapshot.forEach(commentSnapshot => {
            _comments.push(commentSnapshot.data());
            setComments(_comments);

            });

            _comments.map((comment) => { 
                return comment.authorRef.get().then(snapshot => {

                    const { name, profilePictureURL } = snapshot.data();
                    setAuthorInfo({ name, profilePictureURL });
                    if (snapshot.data()) {
                        console.log(authorInfo.profilePictureURL)
                    }

            }) })

        }, (error) => {
            console.log(error);
        });

        return () => listener();

    }, [firestore, slug, comments, authorInfo]);

【问题讨论】:

    标签: reactjs firebase google-cloud-firestore redux-firestore


    【解决方案1】:

    只需在需要呈现用户个人资料图片的任何地方使用它

    <img src={auth.photo} />
    

    并确保您在 App.js 中的 App() 中有这个

    useEffect(() => {
        auth.onAuthStateChanged((authUser) => {
          console.log("user is ", authUser);
          if(authUser){
            dispatch(login({
              uid: authUser.uid,
              photo: authUser.photoURL,
              email: authUser.email,
              displayName: authUser.displayName,
            }))
          }
          else{
            dispatch(logout());
          }
        })
      }, [dispatch])
    
    

    【讨论】:

      【解决方案2】:

      我不确定您是否可以获取非当前登录用户的 Firebase 用户的信息。

      我的建议是将您的每个用户的信息存储在您的数据库中,然后每次用户登录时,您都可以在必要时更新您的数据库。然后,当显示用户的评论时,您在数据库中查找该用户的图片。

      【讨论】:

      • 评论仅适用于经过身份验证的用户,但如果您不介意的话,您能用代码告诉我您的想法吗?我很感激你试图帮助我
      • 代码中没有什么可展示的,主要是你如何构建数据。我的意思是,当您从 firestore 获取 cmets 时,该评论数据的属性应该是发表评论的用户的 uid,而不是个人资料图片。获得该 uid 后,您可以从 firestore 中查找图片,在那里您将拥有一个 users 集合来存储用户数据。并且为了确保图片是最新的,每次用户登录时,您都可以在 Firestore 中更新他们的个人资料图片(如果更改了)。
      【解决方案3】:

      我不是 React 专家,但使用 DocumentReference 可能有助于引用存储在 Firestore 中的 URL。 Here 你可以找到文档来完成这项工作。我想URL是和用户ID相关联的,所以你也可以用它来获取图片的URL。

      【讨论】:

      • 感谢您发表评论,是的,我存储了一个文档引用,但我没有正确实现,我不确定如何将引用与评论放在同一个对象中数据。这是我尝试这样做的代码:pastebin.com/bmdVqRdb
      • 我不熟悉 React 但也许 this 可以帮助你。
      • 是的,谢谢费尔南多,这就是我所说的,我会通读的
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-09-05
      • 2017-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-28
      相关资源
      最近更新 更多