當嘗試拉取陣列時,資料始終為空。有人知道我哪裡出錯了嗎? 我檢查了控制台,據我所知,有一個對 firebase 儲存的引用,但沒有資料。但我的儲存中有 4 個文件應該輸出 URL 連結。 這是我的元件
import React, { useState, useEffect } from 'react'; // i'm initializing firebase with firebase.initializeApp(firebaseConfig) import { projectStorage } from '@/firebaseConfig'; // projectStorage is = firebase.storage(); const PDFViewer = () => { const [pdfUrls, setPdfUrls] = useState(); useEffect(()=>{ const storageRef = projectStorage.ref(); const pdfRef = storageRef.child('myfirebaselocationpath/uploadeddocs/'); const urls = []; pdfRef.listAll().then((result) => { result.items.forEach((itemRef) => { itemRef.getDownloadURL().then((url) => { urls.push(url); }); }); setPdfUrls(urls); }).catch((error) => { console.error('Error retrieving PDF files:', error); }); },[]) console.log(pdfUrls) /* console.log( pdfUrls.map((url) => { return url }) ) */ return ( <div> <h1>PDF Viewer</h1> {pdfUrls.map((url) => ( <iframe key={url} src={url} width="100%" height="600px" /> ))} </div> ); }; export default PDFViewer;`
上面的元件是我嘗試過的,並期望映射連結列表,但沒有顯示任何資料。並且 pdfUrls 始終為空。
P粉9764880152023-09-16 14:36:26
問題出在這裡:
pdfRef.listAll().then((result) => { result.items.forEach((itemRef) => { itemRef.getDownloadURL().then((url) => { urls.push(url); }); }); setPdfUrls(urls);
listAll
和 getDownloadURL
都是非同步操作,可能需要一些時間才能完成。主程式碼不會阻塞整個腳本,而是在操作發生時繼續執行 - 然後當資料(檔案清單或下載 URL)可用時執行回調區塊。
這意味著您的 setPdfUrls(urls);
在任何 urls.push(url);
運行之前運行,並且這會設定空列表。我建議在調試器中檢查這一點,或者添加一些日誌記錄。
解決該問題的最簡單方法是將 setPdfUrls(urls);
移至內部回呼:
pdfRef.listAll().then((result) => { result.items.forEach((itemRef) => { itemRef.getDownloadURL().then((url) => { urls.push(url); setPdfUrls(urls); }); });
現在它會在確定每個下載 URL 後呼叫。這會執行多次更新,因此可能會導致 UI 中出現一些閃爍,但現在資料應該會顯示。
在等待一切完成的同時只呼叫一次 setPdfUrls(urls);
需要做更多的工作。最簡單的方法可能是將整個 useEffect
處理程序標記為 async
並在其中使用 await
:
useEffect(() => async { const storageRef = projectStorage.ref(); const pdfRef = storageRef.child('myfirebaselocationpath/uploadeddocs/'); const urls = []; const result = await pdfRef.listAll(); for (const itemRef of result.items) { const url = await itemRef.getDownloadURL(); urls.push(url); } setPdfUrls(urls); }, [])
所以這段程式碼:
await
確保非同步操作在呼叫 setPdfUrls
之前完成。 for...of
迴圈來確保我們可以在該迴圈內使用 await
。