firebase React组件无法从自定义钩子呈现数据

fnvucqvd  于 2023-04-07  发布在  React
关注(0)|答案(1)|浏览(123)

我正在使用React和Firebase创建社交媒体应用程序。在时间轴组件中,我想渲染我关注的用户的图像。我做了自定义钩子来从Firebase中获取数据。对于图像,最初我得到空数组,然后是useTimeline中的所有图像,但无法渲染任何图像属性。

// hooks
import { useTimeline } from "../../hooks/useTimeline";
// components
import SearchBar from '../../components/search/SearchBar';
// styles
import styles from './Timeline.module.css';

const Timeline = () => {
    const { images } = useTimeline();

    console.log(images) // initially log empty array then all data

    return (
        <div className={styles.timeline}>
            <SearchBar />  //This works
            {images && images.map(image => (    //This doesn't work
                <div key={image.id}>
                    <img src={image.photoURL} alt='post' />
                </div>
            ))}
        </div>
    );
};

export default Timeline;
// hooks
import { useEffect, useState } from 'react';
import { useAuthContext } from './useAuthContext';
// firebase
import { db } from '../firebase/config';
import { collection, where, orderBy, query, getDocs, getDoc, doc } from 'firebase/firestore';

export const useTimeline = () => {
    const [images, setImages] = useState([]);
    const { user } = useAuthContext(); 

    useEffect(() => {
        const getImages = async () => {
            // 1) Find all users that signedIn user is following
            const  followingRef = collection(db, `following/${user.uid}/followingUsers`);
            const followingSnapshot = await getDocs(followingRef);
            let followedUsers = [];
            followingSnapshot.forEach((doc) => {
                followedUsers.push(doc.id);
            });

            // 2) Query all images where userId is in the followedUsers array
            let imagesRef = collection(db, 'images');
            imagesRef = query(imagesRef, where("userId", "in", followedUsers), orderBy("createdAt", "desc"));
            const imagesSnapshot = await getDocs(imagesRef);
            let results = [];
            imagesSnapshot.forEach(async(document) => {
                // 3) Get followedUser data (displayName, photoURL) and push it to image doc
                //    For POST component
                const userDoc = await getDoc(doc(db, 'users', document.data().userId))
                results.push({ ...document.data(), id: document.id, displayName: userDoc.data().displayName, profilePhotoURL: userDoc.data().photoURL });
            });
            setImages(results);
        };
        getImages();
    }, [user]);
    console.log(images)

    return { images };
};

我做错了什么?

kxkpmulp

kxkpmulp1#

罪魁祸首是useEffect钩子中的forEach。它在移动到下一项之前没有等待async函数完成。通过使用Promise.all()解决这个问题。这样,您将等待所有promise结束后再设置状态。

export const useTimeline = () => {
    const [images, setImages] = useState([]);
    const { user } = useAuthContext(); 

    useEffect(() => {
        const getImages = async () => {
            const  followingRef = collection(db, `following/${user.uid}/followingUsers`);
            const followingSnapshot = await getDocs(followingRef);
            let followedUsers = [];
            followingSnapshot.forEach((doc) => {
                followedUsers.push(doc.id);
            });

            let imagesRef = collection(db, 'images');
            imagesRef = query(imagesRef, where("userId", "in", followedUsers), orderBy("createdAt", "desc"));
            const imagesSnapshot = await getDocs(imagesRef);
            
            const resultsPromises = imagesSnapshot.docs.map(async (document) => {
                const userDoc = await getDoc(doc(db, 'users', document.data().userId));
                return { ...document.data(), id: document.id, displayName: userDoc.data().displayName, profilePhotoURL: userDoc.data().photoURL };
            });

            const results = await Promise.all(resultsPromises);
            setImages(results);
        };
        getImages();
    }, [user]);
    console.log(images)

    return { images };
};

相关问题