亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

未從 firestore 獲取數據

未從 firestore 獲取數據

當年話下 2023-06-29 15:52:57
我嘗試從 firestore 獲取文檔,它返回一個空數組,但是當我運行 console.log(docs); 時 在聲明的函數之外,它返回實際的數組。我知道發生此錯誤是因為我的 useEffect 函數在從 firestore 獲取文檔之前首先運行。我想知道如何解決這個問題。const Component = (props) => {    const { docs } = useFirestore('books');    const id = props.match.params.id;        const loadContent = () => {        const book = docs && docs.filter(doc => doc.id === id);        console.log(book); //not getting book from the docs because docs is empty    }        useEffect(() => {        async function getContent(){            await loadContent();        }        getContent()    },[]);};useFirestore.jsimport { useState, useEffect } from 'react';import { firestore } from '../config/fbConfig';const useFirestore = (collection) => {    const [docs, setDocs] = useState([]);    const [loading, setLoading] = useState(true);    // getting realtime data from the firebase for books    useEffect(() => {        let unsubscribe = firestore.collection(collection)        // .orderBy('createdAt', 'desc')        .onSnapshot((querySnapshot) => {          const items = [];          querySnapshot.forEach((doc) => {            items.push({...doc.data(), id: doc.id});          });          setDocs(items);          setLoading(false);        });        return unsubscribe;      }, []); // eslint-disable-line react-hooks/exhaustive-deps      return { docs, loading };}export default useFirestore;
查看完整描述

2 回答

?
慕田峪4524236

TA貢獻1875條經驗 獲得超5個贊

我認為你已經非常接近預期的行為了。我的處理方法如下:


const Component = props => {

  const { docs } = useFirestore("books");


  const id = props.match.params.id;


  // useMemo - whenever `docs` change, recalculate the book variable.

  // If `docs` don't change, `book` will also not change.

  // Your `docs` will probably change on every snapshot.

  const book = useMemo(() => docs && docs.filter(doc => doc.id === id), [docs]);


  console.log(book);


  useEffect(() => {

    if (book) {

      // Do something with the book, e.g. loadContent(book).

      // Keep in mind that this will run on every snapshot.

      // If you only want to run this once, you'll need an

      // extra state variable to store that the effect was

      // already run, and check it here.

    }

  }, [book]); // The effect will run whenever book changes

};

這個useFirestore鉤子看起來幾乎沒問題,只有一件事:現在即使你改變參數collection,快照監聽器也不會改變。您可能想要這樣做:


useEffect(() => {

  const unsubscribe = firestore.collection(collection).onSnapshot(snapshot => {

    const items = snapshot.map(doc => ({ ...doc.data(), id: doc.id }));

    setDocs(items);

    setLoading(false);

  });


  return unsubscribe;


  // Whenever `collection` changes, `unsubscribe` will be called, and then this hook

  // will subscribe to the new collection.

}, [collection]);

更新。

如果您希望useFirestore掛鉤僅查詢特定書籍,則需要更改掛鉤以接受并使用文檔 ID,如下所示:



const getDoc = doc => ({ ...doc.data(), id: doc.id });


const useFirestore = (collection, docId) => {

  const [docs, setDocs] = useState([]);

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


  useEffect(() => {

    let subject = firestore.collection(collection);


    if (docId) {

      // If docId is available, listen for changes to a

      // particular document

      subject = subject.doc(docId);

    }


    const unsubscribe = subject.onSnapshot(snapshot => {

      // Notice here that if listening for a particular docId,

      // the snapshot will be that document, not an array.

      // To maintain the interface of the hook, I convert that

      // document to an array with a single item.

      const items = docId ? [getDoc(doc)] : snapshot.map(getDoc);

      setDocs(items);

      setLoading(false);

    });


    return unsubscribe;

  }, [collection, docId]);


  return { docs, loading };

};


查看完整回答
反對 回復 2023-06-29
?
紅顏莎娜

TA貢獻1842條經驗 獲得超13個贊

我需要有關“useFirestore”代碼的更多信息,但您至少應該這樣編寫代碼。

  • 不要列出 firestore 上的每個文檔來獲取一個(您為每個讀取請求付費)

  • 在 useEffect 中加載文檔,而不是在外部

  • useEffect 必須依賴于 id

   const Component = (props) => {

       const id = props.match.params.id;

       const firestore = //;

       const [book, bookSet] = useState(false);


       useEffect(() => {

           //Depending on useFirestore code

           firestore.collections('books').doc(id)

           .then( snapshot => {

               if ( !snapshot.exists ) {

                   bookSet(null);

               } else {

                   bookSet(snapshot.data());

               }

           });

       }, [id]);


       if( book === false) return <p>Loading</p>

       if (!book) return <p>Not exists</p>

       return <p>Display it</p>;

   };

編輯


這是我對你的“useFirestore”鉤子的猜測


  const Component = (props) => {

      const id = props.match.params.id;

      const { docs, loading } = useFirestore('books');

      

      useEffect(() => {

          if( loading) console.log('Loading');

          return;


          const book = docs && docs.filter(doc => doc.id === id);

          console.log({book});

      },[loading, docs, id]);

  };


查看完整回答
反對 回復 2023-06-29
  • 2 回答
  • 0 關注
  • 150 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號