next.js 如何有效地从Firebase/Firestore子集合中检索数据?

p4tfgftt  于 2022-11-05  发布在  其他
关注(0)|答案(1)|浏览(103)

我使用firestore来存储帖子,每个帖子都可以有简单的属性,如{title:“嗨”,评论:false}我可以轻松地获取用户的特定帖子,因为我的收藏结构如下所示:posts/user.id/post/post.name所以一个例子将是posts/1234 sofa/post/cool day通过这种结构化方式,我能够轻松地为用户获取数据,但是我在两件事上遇到了麻烦:如何为我的主提要获取和显示所有帖子,以及最有效的方法是什么?下面是我目前用于获取用户特定数据的函数:

const submitpost = async () => {
    try {

const collectionRef=collection(db,`posts`,user.uid.toString(),'post')

      await addDoc(collectionRef, {
        post: post,
        timestamp: serverTimestamp(),
        canComment: switchValue,
        user: user.uid,
        avatar: user.photoURL,
        username: user.displayName,
      });
      toast({ title: "posted", status: "success", duration: 2000 });
    } catch (error) {
      console.log(error);
    }
  };

这个特定的函数创建了一个结构,如下所示,在firebase中,posts分别是take和take,分别是single post,我只是更改了名称,这样更容易理解:

现在这里是我如何为我的特定用户获取数据:

const [user] = useAuthState(auth);
      const [takes, settakes] = useState([]);
    const getData = async () => {
    // if user is present run function

    if (user) {
      // const docRef = doc(db, "users", user.uid);
      // const collectionRef = collection(docRef, "takes");
      // const querySnapshot = await getDocs(collectionRef);
      try {
        const docRef = doc(db, "posts", user.uid);
        const collectionRef = collection(db,'posts',user.uid,'takes');
        const querySnapshot = await getDocs(collectionRef);

        const data = querySnapshot.docs.map((d) => ({
          id: d.id,
          ...d.data(),
        }));

        settakes(data);
      } catch (error) {
        console.log(error);
      }

      //
    }
  };

下面是在为main feed获取所有数据时无法工作的函数:

const [user]=useAuthState(auth)
  const [allfeed, setallfeed] = useState([])
    const getData = async () => {
    if(user){
      const collectionRef = collection(db, "posts");
    const querySnapshot = await getDocs(collectionRef);
    const data = querySnapshot.docs.map((d) => ({
      id: d.id,
      ...d.data(),
    }));
  // get data from firebase 
  setallfeed(data)
    }

  }
  useEffect(() => {
    getData()
    console.log('ran');
    console.log(allfeed);

    // rerun when user is present
  }, [user]);

当我控制台记录allfeed时,它返回一个空数组,所以我的主要问题是如何从posts集合中获取所有数据,即posts/userid/post/post.title。我需要为每个用户获取这些数据。其次,是否有更有效的方法来组织我的数据?

5gfr0r5j

5gfr0r5j1#

如果您希望从集合或特定文档中实时更新,我建议您使用onSnapshot()方法。
setState()不会直接更改状态对象。它只是为React核心创建队列,以更新React组件的状态对象。如果您将状态添加到useEffect,它会比较这两个对象,由于它们具有不同的引用,它会再次获取项目并将新的项目对象设置为该状态。然后,状态更新会触发组件中的重新呈现。然后,等等等等。
如果您只想将数据记录到控制台中,则必须使用临时变量而不是setState:

const getData = async () => {
    if(user){
        // Using `getDocs`
        const collectionRef = collection(db, "posts");
        const querySnapshot = await getDocs(collectionRef);
        const data = querySnapshot.docs.map((d) => ({
            id: d.id,
            ...d.data(),
        }));

        console.log(data)

        // ============================================= //

        // Using `onSnapshot()`
        const q = query(collection(db, "posts"));
        const unsubscribe = onSnapshot(q, (querySnapshot) => {
            const data = querySnapshot.docs.map(d => ({
                id: d.id,
                ...d.data()
            }))

            console.log(data)
        });
    }
}

useEffect(() => {
    getData();
}, []);

您也可以使用多个useEffect()来取得对象的更新状态:

const getData = async () => {
    if(user){
        // Using `getDocs`
        const collectionRef = collection(db, "posts");
        const querySnapshot = await getDocs(collectionRef);
        const data = querySnapshot.docs.map((d) => ({
            id: d.id,
            ...d.data(),
        }));

        setallfeed(data)

        // ============================================= //

        // Using `onSnapshot()`
        const q = query(collection(db, "posts"));
        const unsubscribe = onSnapshot(q, (querySnapshot) => {
            const data = querySnapshot.docs.map(d => ({
                id: d.id,
                ...d.data()
            }))

            setallfeed(data)
        });
    }
}

useEffect(() => {
    getData();
}, [])

useEffect(() => {
    console.log(allfeed);
}, [allfeed]);

如果你想把它呈现给组件,那么你应该在组件中调用状态,并把数据Map到它。看一下下面的示例代码:

const getData = async () => {
    if(user){
        // Using `getDocs`
        const collectionRef = collection(db, "posts");
        const querySnapshot = await getDocs(collectionRef);
        const data = querySnapshot.docs.map((d) => ({
            id: d.id,
            ...d.data(),
        }));

        setallfeed(data)

        // ============================================= //

        // Using `onSnapshot()`
        const q = query(collection(db, "posts"));
        const unsubscribe = onSnapshot(q, (querySnapshot) => {
            const data = querySnapshot.docs.map(d => ({
                id: d.id,
                ...d.data()
            }))

            setallfeed(data)
        });
    }
}

useEffect(() => {
    getData()
  }, []);

return (
    <div>
        <p>SomeData: <p/>
        {items.map((item) => (
        <p key={item.id}>{item.fieldname}</p>
        ))}
    </div>
);

有关详细信息,您可以查看以下文档:

相关问题