react中firestore onSnapshot的返回值

问题描述 投票:0回答:1

我在函数中有一个 onSnapshot 查询:

//firebaseutil.js
export async function getShorts(uid) {
const q = query(collection(db, 'shorted'), where('owner', '==', uid));
const unsubscribe = onSnapshot(q, (querySnapshot) => {
const urls = [];
querySnapshot.forEach((doc) => {
  urls.push({
    url: doc.data().url,
    shorturl: doc.data().shorturl,
    hits: doc.data().hits,
  });
});
console.log(urls);
return urls;
});
}

如果我更改 firestore 集合上的数据(如预期),它将正确记录数据并重新记录数据

我正在尝试通过这种方式从用户仪表板访问这些数据:

//dashboard.js
import { getShorts } from '../lib/fbutils';
import { useEffect, useState } from 'react';

export default function Dashboard() {
  const [myurls, setUrls] = useState([]);

  useEffect(() => {
    const fetchShorts = async () => {
      if (user) {
        const urls = await getShorts(user.uid);
        setUrls(urls);
        console.log(myurls);
        console.log(urls);
      }
    };
    fetchShorts();
  }, []);

user.id
已正确设置,而
urls
myurls
都被记录为未定义(我正在考虑至少有一个待处理的 Promise)

这里出了什么问题?我通常使用这种模式来检索数据,但这是我第一次从 firestore 订阅获取数据

javascript reactjs firebase google-cloud-firestore snapshot
1个回答
1
投票

onSnapshot()
不会返回承诺,并且您的
getShorts()
函数会在收到数据之前返回。您可以从该函数返回一个承诺,如下所示:

let fetched = false; 

export function getShorts(uid) {
  return new Promise((resolve, reject) => {
    const q = query(collection(db, 'shorted'), where('owner', '==', uid));
    const unsubscribe = onSnapshot(q, (querySnapshot) => {
      const urls = querySnapstho.docs.map((d) => ({ id: d.id, ...d.data() }))
      
      if (!fetched) {
        // URLs fetched for first time, return value
        fetched = true;
        resolve(urls);
      } else {
        // URLs fetched already, an update received.
        // TODO: Update in state directly
      }
    })
  }) 
}

当您调用该函数时,这应该返回所有 URL

await getShorts(user.uid);
,但是对于稍后收到的更新,您必须直接在状态中更新它们,因为承诺现在已经解决了。

© www.soinside.com 2019 - 2024. All rights reserved.